diff --git a/README.md b/README.md index e14cfed..d63df1b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,164 @@ # README -Feeds Backend to Run jobs +This Project is the answer to : -- [X] github repo starred job -- [] github trending job \ No newline at end of file +``` +接口自动化测试平台需求: +1、可对接 swagger 文档,自动/手动导入接口信息 +2、具备接口信息管理、测试用例管理、测试步骤管理、测试报告管理的功能 +3、具备接口调试的功能 +4、以测试集为单位执行多个测试用例,并生成测试报告 + +API Automation Testing Platform Requirements: + +1. Capable of integrating with Swagger documentation, with the ability to automatically/ manually import interface information. +2. with functions for managing interface information, test case management, test step management, and test report management. +3. Possesses the capability for interface debugging. +4. Executes multiple test cases as a test suite and generates test reports. +``` + +Build A [restack](https://www.restack.io/) like toolkits but for Software QA. + +## Just Work QA Testing Management System + +## Just Work API Recorder + +## Features + +FluentQA Workspace project is JAVA Project includes: + +1. Toolkits to handler QA Daily Work +2. Workspace Server for QA Daily Work +3. Learning JAVA in QA perspective +4. Revisited JAVA after A QA writing JAVA several years +5. Easy to Use, Maintain and extend +6. All Codes are Used for Real Cases +7. All libs have its purpose in QA Daily Work + +But Actually not only for QA, it also for anyone want to create +JAVA Libs or Applications. + +## 1. Software QA: JAVA Revisited Overview + +**Automation Language Perspective**: +![img](docs/1-qa-solution/qa-automation.png) + +**Different Libs Perspective**: + +![img](overall.png) + +## 1.1 QA Java frequent used libs + +- [basic-libs](./components/fluent-builtin) basic JAVA Utils +- [excel-csv-operation](./components/fluent-excel) JAVA Excel/CSV Lib +- [mindmap-operation](./components/fluent-mindmap) JAVA mindmap Lib +- [openapi-operations](./components/fluent-openapi) JAVA openapi lib +- [quick-database-operations](./components/fluent-quickdao) JAVA Database access Lib +- [markdonw-operations](./components/fluentqa-md) JAVA Markdown Lib +- [testlibs](./components/fluent-testlibs) JAVA test libs + +### 2. Real Cases + +## 2.1. How to Build a Just-Working Test Case System in one day + +- [slides](https://fluentqa-revistied.netlify.app/present/tc-mgt-one-day/#/1) + +## 3. Integration Libs + +- [integration with other application](http://github.com/fluent-qa/fluent-integrations.git) + +## stats + +[//]: # (

) + +[//]: # ( ) + +[//]: # ( IHub) + +[//]: # ( IHub) + +[//]: # ( ) + +[//]: # (

) + +--- + +[//]: # (

) + +[//]: # ( ) + +[//]: # ( CII Best Practices Level) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( Gradle Build) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( Space Metric) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( CodeFactor) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( Codecov) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( IHubPub) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( IHubPub) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( Gitter) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( Java Doc) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( IHub Snapshot Repository) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( Maven Central) + +[//]: # ( ) + +[//]: # (

) + +[//]: # (组件库) + +## 🧭 开源贡献指南 + +## 👨‍💻 Contributors + +![Alt](https://repobeats.axiom.co/api/embed/97e9207fda40115a8deccefedc421fa84d02eb17.svg "Repobeats analytics image") + +[//]: # ([![Contributors](https://contrib.rocks/image?repo=ihub-pub/libs)](https://github.com/ihub-pub/libs/graphs/contributors "Contributors")) \ No newline at end of file diff --git a/fluent-app-ext/dashboard/github/counts.sql b/docker/metabase/github/counts.sql similarity index 100% rename from fluent-app-ext/dashboard/github/counts.sql rename to docker/metabase/github/counts.sql diff --git a/fluent-app-ext/dashboard/github/search.sql b/docker/metabase/github/search.sql similarity index 100% rename from fluent-app-ext/dashboard/github/search.sql rename to docker/metabase/github/search.sql diff --git a/fluent-app-ext/dashboard/run-metabase.sh b/docker/metabase/run-metabase.sh similarity index 100% rename from fluent-app-ext/dashboard/run-metabase.sh rename to docker/metabase/run-metabase.sh diff --git a/docker/supabase/run.sh b/docker/supabase/run.sh new file mode 100644 index 0000000..001b5b9 --- /dev/null +++ b/docker/supabase/run.sh @@ -0,0 +1,2 @@ +# go to self host supabase folder +docker-compose up \ No newline at end of file diff --git a/docs/0-setup/README.md b/docs/0-setup/README.md new file mode 100644 index 0000000..1e2c8b8 --- /dev/null +++ b/docs/0-setup/README.md @@ -0,0 +1,15 @@ +# README + +- Setup By AI ChatGPT Prompt + +## 环境准备 + +- 操作系统管理/Docker: OrbStack +- 数据库/Database: Supabase +- 开发环境: JAVA/MAVEN + +## JAVA MAVEN Project Setup With Erupts + +- [] Create Main Entry Point Class +- [] Create App Configuration file +- [] Some Page \ No newline at end of file diff --git a/docs/1-qa-solution/README.md b/docs/1-qa-solution/README.md new file mode 100644 index 0000000..27f66f0 --- /dev/null +++ b/docs/1-qa-solution/README.md @@ -0,0 +1,163 @@ +# README + +This Project is the answer to : + +``` +接口自动化测试平台需求: +1、可对接 swagger 文档,自动/手动导入接口信息 +2、具备接口信息管理、测试用例管理、测试步骤管理、测试报告管理的功能 +3、具备接口调试的功能 +4、以测试集为单位执行多个测试用例,并生成测试报告 + +API Automation Testing Platform Requirements: + +1. Capable of integrating with Swagger documentation, with the ability to automatically/ manually import interface information. +2. with functions for managing interface information, test case management, test step management, and test report management. +3. Possesses the capability for interface debugging. +4. Executes multiple test cases as a test suite and generates test reports. +``` + +Build A [restack](https://www.restack.io/) like toolkits but for Software QA. + + +## Features + + + +FluentQA Workspace project is JAVA Project includes: + +1. Toolkits to handler QA Daily Work +2. Workspace Server for QA Daily Work +3. Learning JAVA in QA perspective +4. Revisited JAVA after A QA writing JAVA several years +5. Easy to Use, Maintain and extend +6. All Codes are Used for Real Cases +7. All libs have its purpose in QA Daily Work + +But Actually not only for QA, it also for anyone want to create +JAVA Libs or Applications. + +## 1. Software QA: JAVA Revisited Overview + +**Automation Language Perspective**: +![img](qa-automation.png) + +**Different Libs Perspective**: + +![img](docs/1-qa-solution/overall.png) + +## 1.1 QA Java frequent used libs + +- [basic-libs](./components/fluent-builtin) basic JAVA Utils +- [excel-csv-operation](./components/fluent-excel) JAVA Excel/CSV Lib +- [mindmap-operation](./components/fluent-mindmap) JAVA mindmap Lib +- [openapi-operations](./components/fluent-openapi) JAVA openapi lib +- [quick-database-operations](./components/fluent-quickdao) JAVA Database access Lib +- [markdonw-operations](./components/fluentqa-md) JAVA Markdown Lib +- [testlibs](./components/fluent-testlibs) JAVA test libs + +### 2. Real Cases + +## 2.1. How to Build a Just-Working Test Case System in one day + +- [slides](https://fluentqa-revistied.netlify.app/present/tc-mgt-one-day/#/1) + +## 3. Integration Libs + +- [integration with other application](http://github.com/fluent-qa/fluent-integrations.git) + +## stats + +[//]: # (

) + +[//]: # ( ) + +[//]: # ( IHub) + +[//]: # ( IHub) + +[//]: # ( ) + +[//]: # (

) + +--- + +[//]: # (

) + +[//]: # ( ) + +[//]: # ( CII Best Practices Level) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( Gradle Build) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( Space Metric) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( CodeFactor) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( Codecov) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( IHubPub) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( IHubPub) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( Gitter) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( Java Doc) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( IHub Snapshot Repository) + +[//]: # ( ) + +[//]: # ( ) + +[//]: # ( Maven Central) + +[//]: # ( ) + +[//]: # (

) + +[//]: # (组件库) + +## 🧭 开源贡献指南 + +## 👨‍💻 Contributors + +![Alt](https://repobeats.axiom.co/api/embed/97e9207fda40115a8deccefedc421fa84d02eb17.svg "Repobeats analytics image") + +[//]: # ([![Contributors](https://contrib.rocks/image?repo=ihub-pub/libs)](https://github.com/ihub-pub/libs/graphs/contributors "Contributors")) \ No newline at end of file diff --git a/docs/1-qa-solution/libs-concept.png b/docs/1-qa-solution/libs-concept.png new file mode 100644 index 0000000..b624a06 Binary files /dev/null and b/docs/1-qa-solution/libs-concept.png differ diff --git a/docs/1-qa-solution/overall.png b/docs/1-qa-solution/overall.png new file mode 100644 index 0000000..b624a06 Binary files /dev/null and b/docs/1-qa-solution/overall.png differ diff --git a/docs/1-qa-solution/qa-automation.png b/docs/1-qa-solution/qa-automation.png new file mode 100644 index 0000000..feec58d Binary files /dev/null and b/docs/1-qa-solution/qa-automation.png differ diff --git a/docs/ai-builder/deepseek-product-project.md b/docs/ai-builder/deepseek-product-project.md new file mode 100644 index 0000000..0d1a7f0 --- /dev/null +++ b/docs/ai-builder/deepseek-product-project.md @@ -0,0 +1,2 @@ +# Deepseek Project/Product Management + diff --git "a/docs/ai-builder/deepssek-\345\277\253\351\200\237\346\236\204\345\273\272.md" "b/docs/ai-builder/deepssek-\345\277\253\351\200\237\346\236\204\345\273\272.md" new file mode 100644 index 0000000..b8da575 --- /dev/null +++ "b/docs/ai-builder/deepssek-\345\277\253\351\200\237\346\236\204\345\273\272.md" @@ -0,0 +1,26 @@ +# DeepSeek and Erupt + +使用DeepSeek和Erupt结合快速构建应用系统. 通过例子说明如何快速构建。 + +以测试管理系统例子,一般测试管理系统包括: + +## 1. 测试模块管理 + +## 2. 测试用例管理 + +- 测试用例增删改查管理 +- 测试用例评审管理 + +## 3. 测试计划管理 + +- 测试计划设定 +- 测试用例选择 +- 测试用例分配 +- 测试用例执行进度 + +## 4. 接口测试管理 +- 接口管理 +- 接口测试用例管理 +- 接口测试结果管理 +- 接口Dashboard展示 + \ No newline at end of file diff --git a/docs/ai-builder/system-prompts.md b/docs/ai-builder/system-prompts.md new file mode 100644 index 0000000..887af9c --- /dev/null +++ b/docs/ai-builder/system-prompts.md @@ -0,0 +1,10 @@ +# JAVA + +- 使用erupt框架构建web应用 +- 目前构建的页面模型如下: + |字段|类型|展示类型| + |---|---|---| + |name|string|文本| + |age|int|文本| + |性别|string|下拉单选| +- 请帮忙生成erupt model代码 \ No newline at end of file diff --git a/docs/feeds/opensource-feeds.md b/docs/feeds/opensource-feeds.md new file mode 100644 index 0000000..1dba80f --- /dev/null +++ b/docs/feeds/opensource-feeds.md @@ -0,0 +1 @@ +# Feeds \ No newline at end of file diff --git a/docs/references.yaml b/docs/references.yaml new file mode 100644 index 0000000..150dd31 --- /dev/null +++ b/docs/references.yaml @@ -0,0 +1,5 @@ +database-docs: + - https://github.com/MirrenTools/screw-driver.git + +libs: + - https://gitee.com/dromara/easy-es.git \ No newline at end of file diff --git a/fluent-apps/pcinfo/README.md b/fluent-apps/pcinfo/README.md new file mode 100644 index 0000000..0c374ce --- /dev/null +++ b/fluent-apps/pcinfo/README.md @@ -0,0 +1,41 @@ +# MooInfo +![logo](assets/windows/MooInfo.ico) + +Visual implementation of OSHI, to view information about the system and hardware. + +Such as OS, processes, memory, CPU, disks, devices, sensors, etc. +## Supported platforms +![Windows](https://img.shields.io/badge/Windows-0078D6?style=for-the-badge&logo=windows&logoColor=A8E4A0) +![Linux](https://img.shields.io/badge/Linux-FCC624?style=for-the-badge&logo=linux&logoColor=black) +![macOS](https://img.shields.io/badge/mac%20os-000000?style=for-the-badge&logo=macos&logoColor=black) + +## Screenshot +![Overview](screenshot/overview_mac.png) +![CPU](screenshot/cpu_mac.png) +![Memory](screenshot/memory_mac.png) +![Detail](screenshot/detail_mac.png) +![Network](screenshot/network_mac.png) +![Power](screenshot/power_mac.png) +![Processes](screenshot/processes_mac.png) +![Storage](screenshot/storage_mac.png) +![Variables](screenshot/variables_mac.png) +![USB](screenshot/usb_windows.png) + +More themes: + +![Theme](screenshot/theme_windows.png) + +[More Screenshot on Windows](screenshot/) +## Download +[https://github.com/rememberber/MooInfo/releases](https://github.com/rememberber/MooInfo/releases) +[https://gitee.com/zhoubochina/MooInfo/releases](https://gitee.com/zhoubochina/MooInfo/releases) + +## Thanks to +[FlatLaf](https://github.com/JFormDesigner/FlatLaf) +[oshi](https://github.com/oshi/oshi) +[Hutool](http://hutool.cn/) +[iconfont](https://www.iconfont.cn/) + +## Development considerations +Before your first start, **set the IntelliJ IDEA as below**, then **maven clean**: +![considerations](assets/material/gui_build.png) diff --git a/fluent-apps/pcinfo/assets/linux/MooInfo.png b/fluent-apps/pcinfo/assets/linux/MooInfo.png new file mode 100644 index 0000000..950b59e Binary files /dev/null and b/fluent-apps/pcinfo/assets/linux/MooInfo.png differ diff --git a/fluent-apps/pcinfo/assets/logo/MooInfo.svg b/fluent-apps/pcinfo/assets/logo/MooInfo.svg new file mode 100644 index 0000000..17dde3f --- /dev/null +++ b/fluent-apps/pcinfo/assets/logo/MooInfo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/fluent-apps/pcinfo/assets/mac/MooInfo.icns b/fluent-apps/pcinfo/assets/mac/MooInfo.icns new file mode 100644 index 0000000..69508cb Binary files /dev/null and b/fluent-apps/pcinfo/assets/mac/MooInfo.icns differ diff --git a/fluent-apps/pcinfo/assets/material/gui_build.png b/fluent-apps/pcinfo/assets/material/gui_build.png new file mode 100644 index 0000000..a33d0b1 Binary files /dev/null and b/fluent-apps/pcinfo/assets/material/gui_build.png differ diff --git a/fluent-apps/pcinfo/assets/windows/MooInfo.ico b/fluent-apps/pcinfo/assets/windows/MooInfo.ico new file mode 100644 index 0000000..8d1e487 Binary files /dev/null and b/fluent-apps/pcinfo/assets/windows/MooInfo.ico differ diff --git a/fluent-apps/pcinfo/pom.xml b/fluent-apps/pcinfo/pom.xml new file mode 100644 index 0000000..db917c5 --- /dev/null +++ b/fluent-apps/pcinfo/pom.xml @@ -0,0 +1,174 @@ + + + 4.0.0 + + io.fluentqa + fluent-apps + 1.0-SNAPSHOT + + + pcinfo + + + UTF-8 + 3.5.1 + 3.5.1 + 3.5.1 + 7.0.3 + 6.6.4 + 1.5.4 + 1.0-alpha3 + 1.2.11 + 5.0.0-alpha.14 + + + + + + cn.hutool + hutool-all + + + + com.formdev + flatlaf + ${flatlaf.version} + + + + com.formdev + flatlaf-extras + ${flatlaf-extras.version} + + + + com.formdev + flatlaf-intellij-themes + ${flatlaf-intellij-themes.version} + + + + + com.intellij + forms_rt + ${forms_rt.version} + + + + + com.github.oshi + oshi-core + ${oshi-core.version} + + + + org.jfree + jfreechart + ${jfreechart.version} + + + + org.apache.commons + commons-imaging + ${imaging.version} + + + + xmlwise + xmlwise + ${xmlwise.version} + + + com.squareup.okhttp3 + okhttp + ${okhttp.version} + + + + + + + + + + com.google.guava + guava + ${guava.version} + + + + + + io.github.fvarrui + javapackager + 1.7.2 + + true + io.fluent.pcinfo.App + true + + + + bundling-for-windows + package + + package + + + windows + true + jdk.crypto.ec + + + + + true + true + true + + + installForAllUsers + true + false + false + true + + compiler:Default.isl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fluent-apps/pcinfo/screenshot/cpu_mac.png b/fluent-apps/pcinfo/screenshot/cpu_mac.png new file mode 100644 index 0000000..24c9636 Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/cpu_mac.png differ diff --git a/fluent-apps/pcinfo/screenshot/cpu_windows.png b/fluent-apps/pcinfo/screenshot/cpu_windows.png new file mode 100644 index 0000000..76c34c8 Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/cpu_windows.png differ diff --git a/fluent-apps/pcinfo/screenshot/detail_mac.png b/fluent-apps/pcinfo/screenshot/detail_mac.png new file mode 100644 index 0000000..135d44b Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/detail_mac.png differ diff --git a/fluent-apps/pcinfo/screenshot/detail_windows.png b/fluent-apps/pcinfo/screenshot/detail_windows.png new file mode 100644 index 0000000..0baf78a Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/detail_windows.png differ diff --git a/fluent-apps/pcinfo/screenshot/memory_mac.png b/fluent-apps/pcinfo/screenshot/memory_mac.png new file mode 100644 index 0000000..f8315ca Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/memory_mac.png differ diff --git a/fluent-apps/pcinfo/screenshot/memory_windows.png b/fluent-apps/pcinfo/screenshot/memory_windows.png new file mode 100644 index 0000000..3d7cb46 Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/memory_windows.png differ diff --git a/fluent-apps/pcinfo/screenshot/network_mac.png b/fluent-apps/pcinfo/screenshot/network_mac.png new file mode 100644 index 0000000..7f65cc6 Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/network_mac.png differ diff --git a/fluent-apps/pcinfo/screenshot/network_windows.png b/fluent-apps/pcinfo/screenshot/network_windows.png new file mode 100644 index 0000000..baf0e3d Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/network_windows.png differ diff --git a/fluent-apps/pcinfo/screenshot/overview_mac.png b/fluent-apps/pcinfo/screenshot/overview_mac.png new file mode 100644 index 0000000..a977b94 Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/overview_mac.png differ diff --git a/fluent-apps/pcinfo/screenshot/overview_windows.png b/fluent-apps/pcinfo/screenshot/overview_windows.png new file mode 100644 index 0000000..d456349 Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/overview_windows.png differ diff --git a/fluent-apps/pcinfo/screenshot/power_mac.png b/fluent-apps/pcinfo/screenshot/power_mac.png new file mode 100644 index 0000000..4e30362 Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/power_mac.png differ diff --git a/fluent-apps/pcinfo/screenshot/power_windows.png b/fluent-apps/pcinfo/screenshot/power_windows.png new file mode 100644 index 0000000..72c036f Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/power_windows.png differ diff --git a/fluent-apps/pcinfo/screenshot/processes_mac.png b/fluent-apps/pcinfo/screenshot/processes_mac.png new file mode 100644 index 0000000..d66a526 Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/processes_mac.png differ diff --git a/fluent-apps/pcinfo/screenshot/processes_windows.png b/fluent-apps/pcinfo/screenshot/processes_windows.png new file mode 100644 index 0000000..967c53d Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/processes_windows.png differ diff --git a/fluent-apps/pcinfo/screenshot/storage_mac.png b/fluent-apps/pcinfo/screenshot/storage_mac.png new file mode 100644 index 0000000..15b61d6 Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/storage_mac.png differ diff --git a/fluent-apps/pcinfo/screenshot/storage_windows.png b/fluent-apps/pcinfo/screenshot/storage_windows.png new file mode 100644 index 0000000..b5bf401 Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/storage_windows.png differ diff --git a/fluent-apps/pcinfo/screenshot/theme_windows.png b/fluent-apps/pcinfo/screenshot/theme_windows.png new file mode 100644 index 0000000..8931f12 Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/theme_windows.png differ diff --git a/fluent-apps/pcinfo/screenshot/usb_windows.png b/fluent-apps/pcinfo/screenshot/usb_windows.png new file mode 100644 index 0000000..e86621f Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/usb_windows.png differ diff --git a/fluent-apps/pcinfo/screenshot/variables_mac.png b/fluent-apps/pcinfo/screenshot/variables_mac.png new file mode 100644 index 0000000..9b73593 Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/variables_mac.png differ diff --git a/fluent-apps/pcinfo/screenshot/variables_windows.png b/fluent-apps/pcinfo/screenshot/variables_windows.png new file mode 100644 index 0000000..a8d8e4d Binary files /dev/null and b/fluent-apps/pcinfo/screenshot/variables_windows.png differ diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/App.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/App.java new file mode 100644 index 0000000..f941499 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/App.java @@ -0,0 +1,104 @@ +package io.fluent.pcinfo; + +import cn.hutool.core.exceptions.ExceptionUtil; +import com.formdev.flatlaf.extras.FlatDesktop; +import com.formdev.flatlaf.extras.FlatInspector; +import com.formdev.flatlaf.extras.FlatUIDefaultsInspector; +import com.formdev.flatlaf.util.SystemInfo; + +import io.fluent.pcinfo.ui.Init; +import io.fluent.pcinfo.ui.dialog.AboutDialog; +import io.fluent.pcinfo.ui.dialog.SettingDialog; +import io.fluent.pcinfo.ui.form.LoadingForm; +import io.fluent.pcinfo.ui.form.MainWindow; +import io.fluent.pcinfo.ui.frame.MainFrame; +import io.fluent.pcinfo.util.*; +import lombok.extern.slf4j.Slf4j; + +import javax.swing.*; +import java.awt.*; + +/** + * Main Enter! + * + * @author RememBerBer + * @since 2021/11/07. + */ +@Slf4j +public class App { + + public static ConfigUtil config = ConfigUtil.getInstance(); + + public static MainFrame mainFrame; + + public static oshi.SystemInfo si; + + public static void main(String[] args) { + + if (SystemInfo.isMacOS) { +// java -Xdock:name="MooInfo" -Xdock:icon=MooInfo.jpg ... (whatever else you normally specify here) +// java -Xms64m -Xmx256m -Dapple.awt.application.name="MooInfo" -Dcom.apple.mrj.application.apple.menu.about.name="MooInfo" -cp "./lib/*" com.luoboduner.moo.info.App + System.setProperty("apple.laf.useScreenMenuBar", "true"); + System.setProperty("apple.awt.application.name", "MooInfo"); + System.setProperty("com.apple.mrj.application.apple.menu.about.name", "MooInfo"); + System.setProperty("apple.awt.application.appearance", "system"); + + FlatDesktop.setAboutHandler(() -> { + try { + AboutDialog dialog = new AboutDialog(); + + dialog.pack(); + dialog.setVisible(true); + } catch (Exception e2) { + log.error(ExceptionUtil.getRootCauseMessage(e2)); + log.error(ExceptionUtil.getMessage(e2)); + } + }); + FlatDesktop.setPreferencesHandler(() -> { + try { + SettingDialog dialog = new SettingDialog(); + + dialog.pack(); + dialog.setVisible(true); + } catch (Exception e2) { + log.error(ExceptionUtil.getRootCauseMessage(e2)); + log.error(ExceptionUtil.getMessage(e2)); + } + }); + FlatDesktop.setQuitHandler(FlatDesktop.QuitResponse::performQuit); + + } + + Init.initTheme(); + + // install inspectors + FlatInspector.install("ctrl shift alt X"); + FlatUIDefaultsInspector.install("ctrl shift alt Y"); + + mainFrame = new MainFrame(); + mainFrame.init(); + JPanel loadingPanel = new LoadingForm().getLoadingPanel(); + mainFrame.add(loadingPanel); + mainFrame.pack(); + mainFrame.setVisible(true); + + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + if (config.isDefaultMaxWindow() || screenSize.getWidth() <= 1366) { + // The window is automatically maximized at low resolution + mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH); + } + + UpgradeUtil.smoothUpgrade(); + + mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + + si = new oshi.SystemInfo(); + + Init.initGlobalFont(); + mainFrame.setContentPane(MainWindow.getInstance().getMainPanel()); + MainWindow.getInstance().init(); + Init.initAllTab(); + Init.initOthers(); + mainFrame.remove(loadingPanel); + } +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/bean/VersionSummary.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/bean/VersionSummary.java new file mode 100644 index 0000000..c67a629 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/bean/VersionSummary.java @@ -0,0 +1,53 @@ +package io.fluent.pcinfo.bean; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * Version summary + * + * @author RememBerBer + * @since 2021/11/08. + */ +@Data +public class VersionSummary implements Serializable { + + private static final long serialVersionUID = 4637273116136790267L; + + /** + * current version + */ + private String currentVersion; + + /** + * version index + */ + private String versionIndex; + + /** + * list of history versions + */ + private List versionDetailList; + + /** + * Version Class + * + * @author RememBerBer + * @since 2021/11/08. + */ + @Data + public static class Version implements Serializable { + + private static final long serialVersionUID = 4637273116136790268L; + + private String version; + + private String title; + + private String log; + + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/Init.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/Init.java new file mode 100644 index 0000000..a98d1d9 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/Init.java @@ -0,0 +1,190 @@ +package io.fluent.pcinfo.ui; + +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.formdev.flatlaf.FlatDarculaLaf; +import com.formdev.flatlaf.FlatDarkLaf; +import com.formdev.flatlaf.FlatIntelliJLaf; +import com.formdev.flatlaf.FlatLightLaf; +import com.formdev.flatlaf.extras.FlatSVGIcon; +import com.formdev.flatlaf.intellijthemes.*; +import com.formdev.flatlaf.themes.FlatMacDarkLaf; +import com.formdev.flatlaf.themes.FlatMacLightLaf; +import io.fluent.pcinfo.App; +import io.fluent.pcinfo.ui.component.TopMenuBar; +import io.fluent.pcinfo.ui.form.*; +import io.fluent.pcinfo.util.SystemUtil; +import io.fluent.pcinfo.util.UIUtil; +import io.fluent.pcinfo.util.UpgradeUtil; + +import javax.swing.*; +import javax.swing.plaf.FontUIResource; +import java.awt.*; +import java.util.Enumeration; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * The init Class + * + * @author RememBerBer + * @since 2021/11/09. + */ +public class Init { + + private static final Log logger = LogFactory.get(); + + /** + * font size inti KEY + */ + private static final String FONT_SIZE_INIT_PROP = "fontSizeInit"; + + /** + * set font for global + */ + public static void initGlobalFont() { + if (StrUtil.isEmpty(App.config.getProps(FONT_SIZE_INIT_PROP))) { + // Adjust the font size according to the DPI + // Gets the resolution of the screen dpi + // dell 1920*1080/24 inch =96 + // Xiaomi air 1920*1080/13.3 inch =144 + // Xiaomi air 1366*768/13.3inch =96 + int fontSize = 12; + + // Initialize high-resolution screen font sizes such as Macs + if (SystemUtil.isMacOs()) { + fontSize = 15; + } else { + fontSize = (int) (UIUtil.getScreenScale() * fontSize); + } + App.config.setFontSize(fontSize); + + App.config.setProps(FONT_SIZE_INIT_PROP, "true"); + App.config.save(); + + TopMenuBar.getInstance().initFontSizeMenu(); + } + + Font font = new Font(App.config.getFont(), Font.PLAIN, App.config.getFontSize()); + FontUIResource fontRes = new FontUIResource(font); + for (Enumeration keys = UIManager.getDefaults().keys(); keys.hasMoreElements(); ) { + Object key = keys.nextElement(); + Object value = UIManager.get(key); + if (value instanceof FontUIResource) { + UIManager.put(key, fontRes); + } + } + + } + + /** + * Other initialization + */ + public static void initOthers() { + + } + + /** + * init look and feel + */ + public static void initTheme() { + + try { + switch (App.config.getTheme()) { + case "System Default": + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + break; + case "Flat Light": + FlatLightLaf.setup(); + break; + case "Flat IntelliJ": + FlatIntelliJLaf.setup(); + break; + case "Flat Dark": + FlatDarkLaf.setup(); + break; + case "Dark purple": + FlatDarkPurpleIJTheme.setup(); + break; + case "IntelliJ Cyan": + FlatCyanLightIJTheme.setup(); + break; + case "IntelliJ Light": + FlatLightFlatIJTheme.setup(); + break; + case "Xcode-Dark": + FlatXcodeDarkIJTheme.setup(); + break; + case "Vuesion": + FlatVuesionIJTheme.setup(); + break; + case "Flat macOS Light": + FlatMacLightLaf.setup(); + break; + case "Flat macOS Dark": + FlatMacDarkLaf.setup(); + break; + default: + FlatDarculaLaf.setup(); + } + + if (UIUtil.isDarkLaf()) { +// FlatSVGIcon.ColorFilter.getInstance().setMapper(color -> color.brighter().brighter()); + } else { + FlatSVGIcon.ColorFilter.getInstance().setMapper(color -> color.darker().darker()); +// SwingUtilities.windowForComponent(App.mainFrame).repaint(); + } + + if (App.config.isUnifiedBackground()) { + UIManager.put("TitlePane.unifiedBackground", true); + } + + // top menubar background + UIManager.put("PopupMenu.background", UIManager.getColor("Panel.background")); + // arrow type + UIManager.put("Component.arrowType", "chevron"); + } catch (Exception e) { + logger.error(e); + } + } + + /** + * init all tab + */ + public static void initAllTab() { + + ThreadUtil.execute(OverviewForm::init); + ThreadUtil.execute(DetailForm::init); + ThreadUtil.execute(MemoryForm::init); + ThreadUtil.execute(CpuForm::init); + ThreadUtil.execute(NetworkForm::init); + ThreadUtil.execute(UsbForm::init); + ThreadUtil.execute(VariablesForm::init); + ThreadUtil.execute(ProcessesForm::init); + ThreadUtil.execute(DiskForm::init); + ThreadUtil.execute(PowerSourceForm::init); + + // Check the new version + if (App.config.isAutoCheckUpdate()) { + ScheduledThreadPoolExecutor threadPoolExecutor = new ScheduledThreadPoolExecutor(1); + threadPoolExecutor.scheduleAtFixedRate(() -> UpgradeUtil.checkUpdate(true), 0, 24, TimeUnit.HOURS); + } + } + + public static void showMainFrame() { + App.mainFrame.setVisible(true); + if (App.mainFrame.getExtendedState() == Frame.ICONIFIED) { + App.mainFrame.setExtendedState(Frame.NORMAL); + } else if (App.mainFrame.getExtendedState() == 7) { + App.mainFrame.setExtendedState(Frame.MAXIMIZED_BOTH); + } + App.mainFrame.requestFocus(); + } + + public static void shutdown() { + App.mainFrame.dispose(); + System.exit(0); + } +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/Style.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/Style.java new file mode 100644 index 0000000..1b9e599 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/Style.java @@ -0,0 +1,46 @@ +package io.fluent.pcinfo.ui; + + +import io.fluent.pcinfo.ui.form.MainWindow; + +import javax.swing.*; +import java.awt.*; + +/** + * customize Swing component style + * + * @author RememBerBer + * @since 2021/11/17. + */ +public class Style { + + /** + * emphatic font for title + * + * @param component + */ + public static void emphaticTitleFont(JComponent component) { + Font font = MainWindow.getInstance().getMainPanel().getFont(); + component.setFont(new Font(font.getName(), Font.BOLD, font.getSize() + 2)); + } + + /** + * emphatic font for label + * + * @param component + */ + public static void emphaticLabelFont(JComponent component) { + Font font = MainWindow.getInstance().getMainPanel().getFont(); + component.setFont(new Font(font.getName(), Font.BOLD, font.getSize())); + } + + /** + * emphatic font for indicator + * + * @param component + */ + public static void emphaticIndicatorFont(JComponent component) { + Font font = MainWindow.getInstance().getMainPanel().getFont(); + component.setFont(new Font(font.getName(), Font.BOLD, font.getSize() + 12)); + } +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/UiConsts.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/UiConsts.java new file mode 100644 index 0000000..d27754e --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/UiConsts.java @@ -0,0 +1,83 @@ +package io.fluent.pcinfo.ui; + +import java.awt.*; + +/** + * constants about UI + * + * @author RememBerBer + * @since 2021/11/08. + */ +public class UiConsts { + + public static final String APP_NAME = "MooInfo"; + public static final String APP_VERSION = "1.1.3"; + + public static final int TABLE_ROW_HEIGHT = 36; + + /** + * Logo-1024*1024 + */ + public static final Image IMAGE_LOGO_1024 = Toolkit.getDefaultToolkit() + .getImage(UiConsts.class.getResource("/icons/logo-1024.png")); + + /** + * Logo-512*512 + */ + public static final Image IMAGE_LOGO_512 = Toolkit.getDefaultToolkit() + .getImage(UiConsts.class.getResource("/icons/logo-512.png")); + + /** + * Logo-256*256 + */ + public static final Image IMAGE_LOGO_256 = Toolkit.getDefaultToolkit() + .getImage(UiConsts.class.getResource("/icons/logo-256.png")); + + /** + * Logo-128*128 + */ + public static final Image IMAGE_LOGO_128 = Toolkit.getDefaultToolkit() + .getImage(UiConsts.class.getResource("/icons/logo-128.png")); + + /** + * Logo-64*64 + */ + public static final Image IMAGE_LOGO_64 = Toolkit.getDefaultToolkit() + .getImage(UiConsts.class.getResource("/icons/logo-64.png")); + + /** + * Logo-48*48 + */ + public static final Image IMAGE_LOGO_48 = Toolkit.getDefaultToolkit() + .getImage(UiConsts.class.getResource("/icons/logo-48.png")); + + /** + * Logo-32*32 + */ + public static final Image IMAGE_LOGO_32 = Toolkit.getDefaultToolkit() + .getImage(UiConsts.class.getResource("/icons/logo-32.png")); + + /** + * Logo-24*24 + */ + public static final Image IMAGE_LOGO_24 = Toolkit.getDefaultToolkit() + .getImage(UiConsts.class.getResource("/icons/logo-24.png")); + + /** + * Logo-16*16 + */ + public static final Image IMAGE_LOGO_16 = Toolkit.getDefaultToolkit() + .getImage(UiConsts.class.getResource("/icons/logo-16.png")); + + /** + * update checking url + */ + public static final String CHECK_VERSION_URL = "https://gitee.com/zhoubochina/MooInfo/raw/master/src/main/resources/version_summary.json"; + + public static final int REFRESH_FAST = 1000; + public static final int REFRESH_SLOW = 5000; + + public static final int REFRESH_SLOWER = 15_000; + + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/component/TopMenuBar.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/component/TopMenuBar.java new file mode 100644 index 0000000..e2ddbc5 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/component/TopMenuBar.java @@ -0,0 +1,403 @@ +package io.fluent.pcinfo.ui.component; + +import cn.hutool.core.exceptions.ExceptionUtil; +import cn.hutool.core.thread.ThreadUtil; +import com.formdev.flatlaf.FlatLaf; +import com.formdev.flatlaf.extras.FlatAnimatedLafChange; +import io.fluent.pcinfo.App; +import io.fluent.pcinfo.ui.Init; +import io.fluent.pcinfo.ui.dialog.AboutDialog; +import io.fluent.pcinfo.ui.dialog.SettingDialog; +import io.fluent.pcinfo.ui.dialog.SystemEnvResultDialog; +import io.fluent.pcinfo.ui.dialog.SystemInfoTestDialog; +import io.fluent.pcinfo.ui.form.MainWindow; +import io.fluent.pcinfo.util.SystemUtil; +import io.fluent.pcinfo.util.UpgradeUtil; +import lombok.extern.slf4j.Slf4j; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.io.File; +import java.util.Map; +import java.util.Properties; + +/** + * The top menu bar + * + * @author RememBerBer + * @since 2021/11/10. + */ +@Slf4j +public class TopMenuBar extends JMenuBar { + + private static TopMenuBar menuBar; + + private static JMenu themeMenu; + + private static JMenu fontFamilyMenu; + + private static JMenu fontSizeMenu; + + private static int initialThemeItemCount = -1; + + private static int initialFontFamilyItemCount = -1; + + private static int initialFontSizeItemCount = -1; + + private static String[] themeNames = { + "System Default", + "Flat Light", + "Flat IntelliJ", + "Flat Dark", + "Flat Darcula(Recommended)", + "Dark purple", + "IntelliJ Cyan", + "IntelliJ Light", + "Xcode-Dark", + "Vuesion", + "Flat macOS Light", + "Flat macOS Dark"}; + + private static String[] fontNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); + + private static String[] fontSizes = { + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17", + "18", + "19", + "20", + "21", + "22", + "23", + "24", + "25", + "26"}; + + private TopMenuBar() { + } + + public static TopMenuBar getInstance() { + if (menuBar == null) { + menuBar = new TopMenuBar(); + } + return menuBar; + } + + public void init() { + TopMenuBar topMenuBar = getInstance(); + // ---------App + JMenu appMenu = new JMenu(); + appMenu.setText("App"); + // Setting + JMenuItem settingMenuItem = new JMenuItem(); + settingMenuItem.setText("Settings"); + settingMenuItem.addActionListener(e -> settingActionPerformed()); + appMenu.add(settingMenuItem); + + // Show logs + JMenuItem logMenuItem = new JMenuItem(); + logMenuItem.setText("Show logs"); + logMenuItem.addActionListener(e -> logActionPerformed()); + appMenu.add(logMenuItem); + + // System Info Test + JMenuItem syInfoTestMenuItem = new JMenuItem(); + syInfoTestMenuItem.setText("System Info Test"); + syInfoTestMenuItem.addActionListener(e -> sysInfoTestActionPerformed()); + appMenu.add(syInfoTestMenuItem); + + // System environment variables + JMenuItem sysEnvMenuItem = new JMenuItem(); + sysEnvMenuItem.setText("System environment variables"); + sysEnvMenuItem.addActionListener(e -> sysEnvActionPerformed()); + appMenu.add(sysEnvMenuItem); + + // Exit + JMenuItem exitMenuItem = new JMenuItem(); + exitMenuItem.setText("Exit"); + exitMenuItem.addActionListener(e -> exitActionPerformed()); + appMenu.add(exitMenuItem); + topMenuBar.add(appMenu); + + // ---------Appearance + JMenu appearanceMenu = new JMenu(); + appearanceMenu.setText("Appearance"); + + JCheckBoxMenuItem defaultMaxWindowitem = new JCheckBoxMenuItem("Maximize window by Default"); + defaultMaxWindowitem.setSelected(App.config.isDefaultMaxWindow()); + defaultMaxWindowitem.addActionListener(e -> { + boolean selected = defaultMaxWindowitem.isSelected(); + if (selected) { + App.mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH); + } else { + App.mainFrame.setExtendedState(JFrame.NORMAL); + } + App.config.setDefaultMaxWindow(selected); + App.config.save(); + }); + appearanceMenu.add(defaultMaxWindowitem); + + JCheckBoxMenuItem unifiedBackgrounditem = new JCheckBoxMenuItem("Window color immersive"); + unifiedBackgrounditem.setSelected(App.config.isUnifiedBackground()); + unifiedBackgrounditem.addActionListener(e -> { + boolean selected = unifiedBackgrounditem.isSelected(); + App.config.setUnifiedBackground(selected); + App.config.save(); + UIManager.put("TitlePane.unifiedBackground", selected); + FlatLaf.updateUI(); + }); + appearanceMenu.add(unifiedBackgrounditem); + + themeMenu = new JMenu(); + themeMenu.setText("Theme"); + + initThemesMenu(); + + appearanceMenu.add(themeMenu); + + fontFamilyMenu = new JMenu(); + fontFamilyMenu.setText("Font Family"); + initFontFamilyMenu(); + + appearanceMenu.add(fontFamilyMenu); + + fontSizeMenu = new JMenu(); + fontSizeMenu.setText("Font Size"); + initFontSizeMenu(); + + appearanceMenu.add(fontSizeMenu); + + topMenuBar.add(appearanceMenu); + + // ---------About + JMenu aboutMenu = new JMenu(); + aboutMenu.setText("About"); + + // Check for Updates + JMenuItem checkForUpdatesItem = new JMenuItem(); + checkForUpdatesItem.setText("Check for Updates"); + checkForUpdatesItem.addActionListener(e -> checkForUpdatesActionPerformed()); + aboutMenu.add(checkForUpdatesItem); + + // About + JMenuItem aboutMenuItem = new JMenuItem(); + aboutMenuItem.setText("About"); + aboutMenuItem.addActionListener(e -> aboutActionPerformed()); + aboutMenu.add(aboutMenuItem); + + topMenuBar.add(aboutMenu); + } + + private void checkForUpdatesActionPerformed() { + ThreadUtil.execute(() -> UpgradeUtil.checkUpdate(false)); + } + + public void initFontSizeMenu() { + + if (initialFontSizeItemCount < 0) + initialFontSizeItemCount = fontSizeMenu.getItemCount(); + else { + // remove old items + for (int i = fontSizeMenu.getItemCount() - 1; i >= initialFontSizeItemCount; i--) + fontSizeMenu.remove(i); + } + for (String fontSize : fontSizes) { + JCheckBoxMenuItem item = new JCheckBoxMenuItem(fontSize); + item.setSelected(fontSize.equals(String.valueOf(App.config.getFontSize()))); + item.addActionListener(this::fontSizeChanged); + fontSizeMenu.add(item); + } + } + + + private void initFontFamilyMenu() { + + if (initialFontFamilyItemCount < 0) + initialFontFamilyItemCount = fontFamilyMenu.getItemCount(); + else { + // remove old items + for (int i = fontFamilyMenu.getItemCount() - 1; i >= initialFontFamilyItemCount; i--) + fontFamilyMenu.remove(i); + } + for (String font : fontNames) { + JCheckBoxMenuItem item = new JCheckBoxMenuItem(font); + item.setSelected(font.equals(App.config.getFont())); + item.addActionListener(this::fontFamilyChanged); + fontFamilyMenu.add(item); + } + } + + private void initThemesMenu() { + + if (initialThemeItemCount < 0) + initialThemeItemCount = themeMenu.getItemCount(); + else { + // remove old items + for (int i = themeMenu.getItemCount() - 1; i >= initialThemeItemCount; i--) + themeMenu.remove(i); + } + for (String themeName : themeNames) { + JCheckBoxMenuItem item = new JCheckBoxMenuItem(themeName); + item.setSelected(themeName.equals(App.config.getTheme())); + item.addActionListener(this::themeChanged); + themeMenu.add(item); + } + } + + private void fontSizeChanged(ActionEvent actionEvent) { + try { + String selectedFontSize = actionEvent.getActionCommand(); + + FlatAnimatedLafChange.showSnapshot(); + + App.config.setFontSize(Integer.parseInt(selectedFontSize)); + App.config.save(); + + Init.initGlobalFont(); + SwingUtilities.updateComponentTreeUI(App.mainFrame); + SwingUtilities.updateComponentTreeUI(MainWindow.getInstance().getTabbedPane()); + +// FlatLaf.updateUI(); + + FlatAnimatedLafChange.hideSnapshotWithAnimation(); + + initFontSizeMenu(); + + } catch (Exception e1) { + JOptionPane.showMessageDialog(MainWindow.getInstance().getMainPanel(), "Save failed!\n\n" + e1.getMessage(), "Failed", + JOptionPane.ERROR_MESSAGE); + log.error(ExceptionUtil.getRootCauseMessage(e1)); + } + } + + + private void fontFamilyChanged(ActionEvent actionEvent) { + try { + String selectedFamily = actionEvent.getActionCommand(); + + FlatAnimatedLafChange.showSnapshot(); + + App.config.setFont(selectedFamily); + App.config.save(); + + Init.initGlobalFont(); + SwingUtilities.updateComponentTreeUI(App.mainFrame); + SwingUtilities.updateComponentTreeUI(MainWindow.getInstance().getTabbedPane()); + +// FlatLaf.updateUI(); + + FlatAnimatedLafChange.hideSnapshotWithAnimation(); + + initFontFamilyMenu(); + + } catch (Exception e1) { + JOptionPane.showMessageDialog(MainWindow.getInstance().getMainPanel(), "Save failed!\n\n" + e1.getMessage(), "Failed", + JOptionPane.ERROR_MESSAGE); + log.error(ExceptionUtil.getRootCauseMessage(e1)); + } + } + + private void themeChanged(ActionEvent actionEvent) { + try { + String selectedThemeName = actionEvent.getActionCommand(); + + FlatAnimatedLafChange.showSnapshot(); + + App.config.setTheme(selectedThemeName); + App.config.save(); + + Init.initTheme(); + SwingUtilities.updateComponentTreeUI(App.mainFrame); + SwingUtilities.updateComponentTreeUI(MainWindow.getInstance().getTabbedPane()); + +// FlatLaf.updateUI(); + + FlatAnimatedLafChange.hideSnapshotWithAnimation(); + + initThemesMenu(); + + } catch (Exception e1) { + JOptionPane.showMessageDialog(MainWindow.getInstance().getMainPanel(), "Save failed!\n\n" + e1.getMessage(), "Failed", + JOptionPane.ERROR_MESSAGE); + log.error(ExceptionUtil.getRootCauseMessage(e1)); } + } + + private void aboutActionPerformed() { + try { + AboutDialog dialog = new AboutDialog(); + + dialog.pack(); + dialog.setVisible(true); + } catch (Exception e2) { + log.error(ExceptionUtil.getRootCauseMessage(e2)); + } + } + + private void sysInfoTestActionPerformed() { + try { + SystemInfoTestDialog dialog = new SystemInfoTestDialog(); + dialog.pack(); + dialog.setVisible(true); + } catch (Exception e2) { + log.error("Show system info test dialog failed", e2); + } + } + + private void sysEnvActionPerformed() { + try { + SystemEnvResultDialog dialog = new SystemEnvResultDialog(); + + dialog.appendTextArea("------------System.getenv---------------"); + Map map = System.getenv(); + for (Map.Entry envEntry : map.entrySet()) { + dialog.appendTextArea(envEntry.getKey() + "=" + envEntry.getValue()); + } + + dialog.appendTextArea("------------System.getProperties---------------"); + Properties properties = System.getProperties(); + for (Map.Entry objectObjectEntry : properties.entrySet()) { + dialog.appendTextArea(objectObjectEntry.getKey() + "=" + objectObjectEntry.getValue()); + } + + dialog.pack(); + dialog.setVisible(true); + } catch (Exception e2) { + log.error("Show system environment variables failed", e2); + } + } + + private void logActionPerformed() { + try { + Desktop desktop = Desktop.getDesktop(); + desktop.open(new File(SystemUtil.LOG_DIR)); + } catch (Exception e2) { + log.error("Show log failed", e2); + } + } + + private void exitActionPerformed() { + Init.shutdown(); + } + + private void settingActionPerformed() { + try { + SettingDialog dialog = new SettingDialog(); + + dialog.pack(); + dialog.setVisible(true); + } catch (Exception e2) { + log.error(ExceptionUtil.getRootCauseMessage(e2)); } + } +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/AboutDialog.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/AboutDialog.form new file mode 100644 index 0000000..8d0dd79 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/AboutDialog.form @@ -0,0 +1,352 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/AboutDialog.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/AboutDialog.java new file mode 100644 index 0000000..1fa9bd5 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/AboutDialog.java @@ -0,0 +1,529 @@ +package io.fluent.pcinfo.ui.dialog; + +import cn.hutool.core.thread.ThreadUtil; +import com.formdev.flatlaf.extras.FlatSVGIcon; +import com.formdev.flatlaf.util.SystemInfo; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; +import io.fluent.pcinfo.App; +import io.fluent.pcinfo.ui.UiConsts; +import io.fluent.pcinfo.util.ComponentUtil; +import io.fluent.pcinfo.util.ScrollUtil; +import io.fluent.pcinfo.util.SystemUtil; +import io.fluent.pcinfo.util.UpgradeUtil; + + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import javax.swing.plaf.FontUIResource; +import javax.swing.text.StyleContext; +import java.awt.*; +import java.awt.event.*; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Locale; + +public class AboutDialog extends JDialog { + private JPanel contentPane; + private JScrollPane scrollPane; + private JLabel versionLabel; + private JLabel codeGitHubLabel; + private JLabel codeGiteeLabel; + private JLabel issueLabel; + private JLabel hutoolLabel; + private JLabel iconFontLabel; + private JLabel wePushLinkLabel; + private JPanel wePushPanel; + private JLabel authorLabel; + private JLabel logoLabel; + private JLabel flatLafLabel; + private JPanel mooToolPanel; + private JLabel httpsGithubComRememberberLabel; + private JLabel oshiLabel; + + public AboutDialog() { + + super(App.mainFrame, "About"); + ComponentUtil.setPreferSizeAndLocateToCenter(this, 0.5, 0.64); + setContentPane(contentPane); + setModal(true); + + if (SystemUtil.isMacOs() && SystemInfo.isMacFullWindowContentSupported) { + this.getRootPane().putClientProperty("apple.awt.fullWindowContent", true); + this.getRootPane().putClientProperty("apple.awt.transparentTitleBar", true); + this.getRootPane().putClientProperty("apple.awt.fullscreenable", true); + this.getRootPane().putClientProperty("apple.awt.windowTitleVisible", false); + GridLayoutManager gridLayoutManager = (GridLayoutManager) contentPane.getLayout(); + gridLayoutManager.setMargin(new Insets(28, 0, 0, 0)); + } + + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + onOK(); + } + }); + + // call onCancel() on ESCAPE + contentPane.registerKeyboardAction(e -> onOK(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + + logoLabel.setIcon(new FlatSVGIcon("icons/logo-128.svg")); + versionLabel.setText(UiConsts.APP_VERSION); + + ScrollUtil.smoothPane(scrollPane); + contentPane.updateUI(); + + logoLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + Desktop desktop = Desktop.getDesktop(); + try { + desktop.browse(new URI("https://rememberber.github.io/MooInfo/")); + } catch (IOException | URISyntaxException e1) { + e1.printStackTrace(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + } + + @Override + public void mouseEntered(MouseEvent e) { + super.mouseEntered(e); + e.getComponent().setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + }); + authorLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + Desktop desktop = Desktop.getDesktop(); + try { + desktop.browse(new URI("http://www.luoboduner.com/")); + } catch (IOException | URISyntaxException e1) { + e1.printStackTrace(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + } + + @Override + public void mouseEntered(MouseEvent e) { + super.mouseEntered(e); + e.getComponent().setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + }); + codeGitHubLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + Desktop desktop = Desktop.getDesktop(); + try { + desktop.browse(new URI("https://github.com/rememberber/MooInfo")); + } catch (IOException | URISyntaxException e1) { + e1.printStackTrace(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + } + + @Override + public void mouseEntered(MouseEvent e) { + super.mouseEntered(e); + e.getComponent().setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + }); + codeGiteeLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + Desktop desktop = Desktop.getDesktop(); + try { + desktop.browse(new URI("https://gitee.com/zhoubochina/MooInfo")); + } catch (IOException | URISyntaxException e1) { + e1.printStackTrace(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + } + + @Override + public void mouseEntered(MouseEvent e) { + super.mouseEntered(e); + e.getComponent().setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + }); + issueLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + Desktop desktop = Desktop.getDesktop(); + try { + desktop.browse(new URI("https://github.com/rememberber/MooInfo/issues")); + } catch (IOException | URISyntaxException e1) { + e1.printStackTrace(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + } + + @Override + public void mouseEntered(MouseEvent e) { + super.mouseEntered(e); + e.getComponent().setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + }); + flatLafLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + Desktop desktop = Desktop.getDesktop(); + try { + desktop.browse(new URI("https://github.com/JFormDesigner/FlatLaf")); + } catch (IOException | URISyntaxException e1) { + e1.printStackTrace(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + } + + @Override + public void mouseEntered(MouseEvent e) { + super.mouseEntered(e); + e.getComponent().setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + }); + oshiLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + Desktop desktop = Desktop.getDesktop(); + try { + desktop.browse(new URI("https://github.com/oshi/oshi")); + } catch (IOException | URISyntaxException e1) { + e1.printStackTrace(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + } + + @Override + public void mouseEntered(MouseEvent e) { + super.mouseEntered(e); + e.getComponent().setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + }); + hutoolLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + Desktop desktop = Desktop.getDesktop(); + try { + desktop.browse(new URI("https://hutool.cn/")); + } catch (IOException | URISyntaxException e1) { + e1.printStackTrace(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + } + + @Override + public void mouseEntered(MouseEvent e) { + super.mouseEntered(e); + e.getComponent().setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + }); + wePushPanel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + Desktop desktop = Desktop.getDesktop(); + try { + desktop.browse(new URI("https://github.com/rememberber/WePush")); + } catch (IOException | URISyntaxException e1) { + e1.printStackTrace(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + } + + @Override + public void mouseEntered(MouseEvent e) { + super.mouseEntered(e); + e.getComponent().setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + }); + mooToolPanel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + Desktop desktop = Desktop.getDesktop(); + try { + desktop.browse(new URI("https://github.com/rememberber/MooTool")); + } catch (IOException | URISyntaxException e1) { + e1.printStackTrace(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + } + + @Override + public void mouseEntered(MouseEvent e) { + super.mouseEntered(e); + e.getComponent().setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + }); + iconFontLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + Desktop desktop = Desktop.getDesktop(); + try { + desktop.browse(new URI("https://www.iconfont.cn/")); + } catch (IOException | URISyntaxException e1) { + e1.printStackTrace(); + } + } + + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + } + + @Override + public void mouseEntered(MouseEvent e) { + super.mouseEntered(e); + e.getComponent().setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + }); + // Check for updates + versionLabel.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + ThreadUtil.execute(() -> UpgradeUtil.checkUpdate(false)); + } + + @Override + public void mouseEntered(MouseEvent e) { + super.mouseEntered(e); + e.getComponent().setCursor(new Cursor(Cursor.HAND_CURSOR)); + } + }); + } + + private void onOK() { + // add your code here + dispose(); + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + contentPane = new JPanel(); + contentPane.setLayout(new GridLayoutManager(1, 1, new Insets(20, 20, 20, 20), -1, -1)); + scrollPane = new JScrollPane(); + contentPane.add(scrollPane, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + scrollPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); + final JPanel panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(9, 2, new Insets(10, 10, 0, 0), -1, -1)); + scrollPane.setViewportView(panel1); + panel1.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); + logoLabel = new JLabel(); + logoLabel.setIcon(new ImageIcon(getClass().getResource("/icons/logo-128.png"))); + logoLabel.setText(""); + panel1.add(logoLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + panel1.add(spacer1, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final Spacer spacer2 = new Spacer(); + panel1.add(spacer2, new GridConstraints(8, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel2 = new JPanel(); + panel2.setLayout(new GridLayoutManager(3, 1, new Insets(5, 3, 20, 0), -1, -1)); + panel1.add(panel2, new GridConstraints(1, 0, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + panel2.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "MooInfo", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, this.$$$getFont$$$(null, Font.BOLD, 20, panel2.getFont()), new Color(-4425028))); + final JLabel label1 = new JLabel(); + label1.setText("Visual implementation of OSHI, to view information about the system and hardware"); + panel2.add(label1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + authorLabel = new JLabel(); + authorLabel.setText("Proudly by RememBerBer 周波"); + panel2.add(authorLabel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + versionLabel = new JLabel(); + Font versionLabelFont = this.$$$getFont$$$(null, Font.BOLD, -1, versionLabel.getFont()); + if (versionLabelFont != null) versionLabel.setFont(versionLabelFont); + versionLabel.setText("v0.0.0"); + versionLabel.setToolTipText("Check for updates"); + panel2.add(versionLabel, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel3 = new JPanel(); + panel3.setLayout(new GridLayoutManager(4, 1, new Insets(5, 3, 20, 0), -1, -1)); + panel1.add(panel3, new GridConstraints(2, 0, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + panel3.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "About", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, this.$$$getFont$$$(null, Font.BOLD, -1, panel3.getFont()), null)); + final JLabel label2 = new JLabel(); + label2.setText("Hi. Thanks to use MooInfo. \"Moo\" named from my daughter."); + panel3.add(label2, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label3 = new JLabel(); + label3.setText("I developed this app like my daughter's building toy blocks, "); + panel3.add(label3, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label4 = new JLabel(); + label4.setText("just putting the off-the-shelf open source tools together."); + panel3.add(label4, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label5 = new JLabel(); + label5.setText("Hope you enjoy using it as much as I did building it."); + panel3.add(label5, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel4 = new JPanel(); + panel4.setLayout(new GridLayoutManager(2, 1, new Insets(5, 3, 20, 0), -1, -1)); + panel1.add(panel4, new GridConstraints(3, 0, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + panel4.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "CODE", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, this.$$$getFont$$$(null, Font.BOLD, -1, panel4.getFont()), null)); + codeGitHubLabel = new JLabel(); + codeGitHubLabel.setText("GitHub:https://github.com/rememberber/MooInfo"); + panel4.add(codeGitHubLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + codeGiteeLabel = new JLabel(); + codeGiteeLabel.setText("Gitee:https://gitee.com/zhoubochina/MooInfo"); + panel4.add(codeGiteeLabel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel5 = new JPanel(); + panel5.setLayout(new GridLayoutManager(1, 1, new Insets(5, 3, 20, 0), -1, -1)); + panel1.add(panel5, new GridConstraints(4, 0, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + panel5.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "HELP TO DO BETTER", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, this.$$$getFont$$$(null, Font.BOLD, -1, panel5.getFont()), null)); + issueLabel = new JLabel(); + issueLabel.setText("https://github.com/rememberber/MooInfo/issues"); + panel5.add(issueLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel6 = new JPanel(); + panel6.setLayout(new GridLayoutManager(5, 1, new Insets(5, 3, 20, 0), -1, -1)); + panel1.add(panel6, new GridConstraints(5, 0, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + panel6.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "THANKS TO", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, this.$$$getFont$$$(null, Font.BOLD, -1, panel6.getFont()), null)); + flatLafLabel = new JLabel(); + flatLafLabel.setText("FlatLaf"); + panel6.add(flatLafLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + oshiLabel = new JLabel(); + oshiLabel.setText("oshi"); + panel6.add(oshiLabel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + hutoolLabel = new JLabel(); + hutoolLabel.setText("Hutool"); + panel6.add(hutoolLabel, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + iconFontLabel = new JLabel(); + iconFontLabel.setText("iconfont"); + panel6.add(iconFontLabel, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label6 = new JLabel(); + label6.setText("Some codes and feature were copied from the demo project of oshi."); + panel6.add(label6, new GridConstraints(4, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel7 = new JPanel(); + panel7.setLayout(new GridLayoutManager(1, 1, new Insets(5, 3, 20, 0), -1, -1)); + panel1.add(panel7, new GridConstraints(6, 0, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + panel7.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "SPONSOR", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, this.$$$getFont$$$(null, Font.BOLD, -1, panel7.getFont()), null)); + final JLabel label7 = new JLabel(); + label7.setIcon(new ImageIcon(getClass().getResource("/icons/wx-zanshang.jpg"))); + label7.setText(""); + label7.setToolTipText("感谢您的鼓励和支持"); + panel7.add(label7, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel8 = new JPanel(); + panel8.setLayout(new GridLayoutManager(2, 1, new Insets(5, 3, 20, 0), -1, -1)); + panel1.add(panel8, new GridConstraints(7, 0, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + panel8.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "OTHER WORKS", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, this.$$$getFont$$$(null, Font.BOLD, -1, panel8.getFont()), null)); + wePushPanel = new JPanel(); + wePushPanel.setLayout(new GridLayoutManager(4, 1, new Insets(0, 0, 0, 0), -1, -1)); + panel8.add(wePushPanel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + wePushLinkLabel = new JLabel(); + wePushLinkLabel.setText("https://github.com/rememberber/WePush"); + wePushPanel.add(wePushLinkLabel, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label8 = new JLabel(); + label8.setIcon(new ImageIcon(getClass().getResource("/icons/WePush-logo-64.png"))); + label8.setText(""); + wePushPanel.add(label8, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label9 = new JLabel(); + label9.setText("WePush"); + wePushPanel.add(label9, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label10 = new JLabel(); + label10.setText("专注批量推送的小而美的工具"); + wePushPanel.add(label10, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + mooToolPanel = new JPanel(); + mooToolPanel.setLayout(new GridLayoutManager(4, 1, new Insets(0, 0, 0, 0), -1, -1)); + panel8.add(mooToolPanel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + httpsGithubComRememberberLabel = new JLabel(); + httpsGithubComRememberberLabel.setText("https://github.com/rememberber/MooTool"); + mooToolPanel.add(httpsGithubComRememberberLabel, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label11 = new JLabel(); + label11.setIcon(new ImageIcon(getClass().getResource("/icons/MooTool-logo-64.png"))); + label11.setText(""); + mooToolPanel.add(label11, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label12 = new JLabel(); + label12.setText("MooTool"); + mooToolPanel.add(label12, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label13 = new JLabel(); + label13.setText("A handy tool set for developers."); + mooToolPanel.add(label13, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + } + + /** + * @noinspection ALL + */ + private Font $$$getFont$$$(String fontName, int style, int size, Font currentFont) { + if (currentFont == null) return null; + String resultName; + if (fontName == null) { + resultName = currentFont.getName(); + } else { + Font testFont = new Font(fontName, Font.PLAIN, 10); + if (testFont.canDisplay('a') && testFont.canDisplay('1')) { + resultName = fontName; + } else { + resultName = currentFont.getName(); + } + } + Font font = new Font(resultName, style >= 0 ? style : currentFont.getStyle(), size >= 0 ? size : currentFont.getSize()); + boolean isMac = System.getProperty("os.name", "").toLowerCase(Locale.ENGLISH).startsWith("mac"); + Font fontWithFallback = isMac ? new Font(font.getFamily(), font.getStyle(), font.getSize()) : new StyleContext().getFont(font.getFamily(), font.getStyle(), font.getSize()); + return fontWithFallback instanceof FontUIResource ? fontWithFallback : new FontUIResource(fontWithFallback); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return contentPane; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/SettingDialog.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/SettingDialog.form new file mode 100644 index 0000000..5e47749 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/SettingDialog.form @@ -0,0 +1,97 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/SettingDialog.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/SettingDialog.java new file mode 100644 index 0000000..e1a70a4 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/SettingDialog.java @@ -0,0 +1,161 @@ +package io.fluent.pcinfo.ui.dialog; + +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.formdev.flatlaf.util.SystemInfo; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; +import io.fluent.pcinfo.App; +import io.fluent.pcinfo.util.ComponentUtil; +import io.fluent.pcinfo.util.ScrollUtil; +import io.fluent.pcinfo.util.SystemUtil; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import javax.swing.plaf.FontUIResource; +import javax.swing.text.StyleContext; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.Locale; + +public class SettingDialog extends JDialog { + + private static final Log logger = LogFactory.get(); + + private JPanel contentPane; + private JScrollPane settingScrollPane; + private JCheckBox autoCheckUpdateCheckBox; + private JComboBox comboBox1; + + public SettingDialog() { + + super(App.mainFrame, "Settings"); + ComponentUtil.setPreferSizeAndLocateToCenter(this, 0.5, 0.6); + setContentPane(contentPane); + setModal(true); + + if (SystemUtil.isMacOs() && SystemInfo.isMacFullWindowContentSupported) { + this.getRootPane().putClientProperty("apple.awt.fullWindowContent", true); + this.getRootPane().putClientProperty("apple.awt.transparentTitleBar", true); + this.getRootPane().putClientProperty("apple.awt.fullscreenable", true); + this.getRootPane().putClientProperty("apple.awt.windowTitleVisible", false); + GridLayoutManager gridLayoutManager = (GridLayoutManager) contentPane.getLayout(); + gridLayoutManager.setMargin(new Insets(28, 0, 0, 0)); + } + + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + onOK(); + } + }); + + // call onCancel() on ESCAPE + contentPane.registerKeyboardAction(e -> onOK(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + + // Set the scroll bar speed + ScrollUtil.smoothPane(settingScrollPane); + + // routine + autoCheckUpdateCheckBox.setSelected(App.config.isAutoCheckUpdate()); + + contentPane.updateUI(); + + // Settings-routine-Updates are checked automatically at startup + autoCheckUpdateCheckBox.addActionListener(e -> { + App.config.setAutoCheckUpdate(autoCheckUpdateCheckBox.isSelected()); + App.config.save(); + }); + + } + + private void onOK() { + // add your code here + dispose(); + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + contentPane = new JPanel(); + contentPane.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + settingScrollPane = new JScrollPane(); + contentPane.add(settingScrollPane, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + settingScrollPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); + final JPanel panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(2, 2, new Insets(20, 20, 10, 10), -1, -1)); + settingScrollPane.setViewportView(panel1); + final Spacer spacer1 = new Spacer(); + panel1.add(spacer1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel2 = new JPanel(); + panel2.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + panel1.add(panel2, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, new Dimension(600, -1), null, 0, false)); + final JPanel panel3 = new JPanel(); + panel3.setLayout(new GridLayoutManager(2, 3, new Insets(15, 15, 25, 0), -1, -1)); + panel2.add(panel3, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + panel3.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "Routine", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, this.$$$getFont$$$(null, Font.BOLD, -1, panel3.getFont()), null)); + autoCheckUpdateCheckBox = new JCheckBox(); + autoCheckUpdateCheckBox.setText("Automatically check for updates"); + panel3.add(autoCheckUpdateCheckBox, new GridConstraints(0, 0, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label1 = new JLabel(); + label1.setText("Language"); + panel3.add(label1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + comboBox1 = new JComboBox(); + comboBox1.setEnabled(false); + final DefaultComboBoxModel defaultComboBoxModel1 = new DefaultComboBoxModel(); + defaultComboBoxModel1.addElement("English"); + defaultComboBoxModel1.addElement("简体中文"); + comboBox1.setModel(defaultComboBoxModel1); + panel3.add(comboBox1, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer2 = new Spacer(); + panel3.add(spacer2, new GridConstraints(1, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final Spacer spacer3 = new Spacer(); + panel1.add(spacer3, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + } + + /** + * @noinspection ALL + */ + private Font $$$getFont$$$(String fontName, int style, int size, Font currentFont) { + if (currentFont == null) return null; + String resultName; + if (fontName == null) { + resultName = currentFont.getName(); + } else { + Font testFont = new Font(fontName, Font.PLAIN, 10); + if (testFont.canDisplay('a') && testFont.canDisplay('1')) { + resultName = fontName; + } else { + resultName = currentFont.getName(); + } + } + Font font = new Font(resultName, style >= 0 ? style : currentFont.getStyle(), size >= 0 ? size : currentFont.getSize()); + boolean isMac = System.getProperty("os.name", "").toLowerCase(Locale.ENGLISH).startsWith("mac"); + Font fontWithFallback = isMac ? new Font(font.getFamily(), font.getStyle(), font.getSize()) : new StyleContext().getFont(font.getFamily(), font.getStyle(), font.getSize()); + return fontWithFallback instanceof FontUIResource ? fontWithFallback : new FontUIResource(fontWithFallback); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return contentPane; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/SystemEnvResultDialog.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/SystemEnvResultDialog.form new file mode 100644 index 0000000..bd60337 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/SystemEnvResultDialog.form @@ -0,0 +1,69 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/SystemEnvResultDialog.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/SystemEnvResultDialog.java new file mode 100644 index 0000000..9faa655 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/SystemEnvResultDialog.java @@ -0,0 +1,117 @@ +package io.fluent.pcinfo.ui.dialog; + +import com.formdev.flatlaf.util.SystemInfo; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; +import io.fluent.pcinfo.App; +import io.fluent.pcinfo.ui.UiConsts; +import io.fluent.pcinfo.util.ComponentUtil; +import io.fluent.pcinfo.util.ScrollUtil; +import io.fluent.pcinfo.util.SystemUtil; +import io.fluent.pcinfo.util.UpgradeUtil; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +public class SystemEnvResultDialog extends JDialog { + private JPanel contentPane; + private JButton buttonOK; + private JTextArea textArea1; + + public SystemEnvResultDialog() { + + super(App.mainFrame, "System environment variables"); + ComponentUtil.setPreferSizeAndLocateToCenter(this, 0.4, 0.64); + setContentPane(contentPane); + setModal(true); + getRootPane().setDefaultButton(buttonOK); + + if (SystemUtil.isMacOs() && SystemInfo.isMacFullWindowContentSupported) { + this.getRootPane().putClientProperty("apple.awt.fullWindowContent", true); + this.getRootPane().putClientProperty("apple.awt.transparentTitleBar", true); + this.getRootPane().putClientProperty("apple.awt.fullscreenable", true); + this.getRootPane().putClientProperty("apple.awt.windowTitleVisible", false); + GridLayoutManager gridLayoutManager = (GridLayoutManager) contentPane.getLayout(); + gridLayoutManager.setMargin(new Insets(28, 0, 0, 0)); + } + + buttonOK.addActionListener(e -> onOK()); + + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + onOK(); + } + }); + + // call onCancel() on ESCAPE + contentPane.registerKeyboardAction(e -> onOK(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + + } + + private void onOK() { + // add your code here + dispose(); + } + + public void setTextArea(String str) { + textArea1.setText(str); + } + + public void appendTextArea(String str) { + textArea1.append(str); + textArea1.append("\n"); + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + contentPane = new JPanel(); + contentPane.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + final JPanel panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(1, 2, new Insets(0, 0, 10, 10), -1, -1)); + contentPane.add(panel1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, 1, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + panel1.add(spacer1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final JPanel panel2 = new JPanel(); + panel2.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + panel1.add(panel2, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + buttonOK = new JButton(); + buttonOK.setText("OK"); + panel2.add(buttonOK, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel3 = new JPanel(); + panel3.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + contentPane.add(panel3, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JScrollPane scrollPane1 = new JScrollPane(); + panel3.add(scrollPane1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + scrollPane1.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); + textArea1 = new JTextArea(); + scrollPane1.setViewportView(textArea1); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return contentPane; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/SystemInfoTestDialog.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/SystemInfoTestDialog.form new file mode 100644 index 0000000..5834343 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/SystemInfoTestDialog.form @@ -0,0 +1,77 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/SystemInfoTestDialog.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/SystemInfoTestDialog.java new file mode 100644 index 0000000..1552192 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/SystemInfoTestDialog.java @@ -0,0 +1,461 @@ +package io.fluent.pcinfo.ui.dialog; + +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; +import io.fluent.pcinfo.App; +import io.fluent.pcinfo.ui.UiConsts; +import io.fluent.pcinfo.util.*; +import oshi.SystemInfo; +import oshi.hardware.*; +import oshi.software.os.*; +import oshi.util.FormatUtil; +import oshi.util.Util; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.time.Instant; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class SystemInfoTestDialog extends JDialog { + private static final Log logger = LogFactory.get(); + + private JPanel contentPane; + private JButton buttonOK; + private JButton buttonCancel; + private JTextArea textArea1; + + public SystemInfoTestDialog() { + super(App.mainFrame, "System Info Test"); + ComponentUtil.setPreferSizeAndLocateToCenter(this, App.mainFrame.getWidth(), App.mainFrame.getHeight()); + setContentPane(contentPane); + setModal(true); + getRootPane().setDefaultButton(buttonOK); + + if (SystemUtil.isMacOs() && com.formdev.flatlaf.util.SystemInfo.isMacFullWindowContentSupported) { + this.getRootPane().putClientProperty("apple.awt.fullWindowContent", true); + this.getRootPane().putClientProperty("apple.awt.transparentTitleBar", true); + this.getRootPane().putClientProperty("apple.awt.fullscreenable", true); + this.getRootPane().putClientProperty("apple.awt.windowTitleVisible", false); + GridLayoutManager gridLayoutManager = (GridLayoutManager) contentPane.getLayout(); + gridLayoutManager.setMargin(new Insets(28, 0, 0, 0)); + } + + buttonOK.addActionListener(e -> onOK()); + + buttonCancel.addActionListener(e -> onCancel()); + + // call onCancel() when cross is clicked + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + onCancel(); + } + }); + + // call onCancel() on ESCAPE + contentPane.registerKeyboardAction(e -> onCancel(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + } + + private void onOK() { + ThreadUtil.execute(this::sysInfoTest); + } + + private void sysInfoTest() { + logger.info("Initializing System..."); + SystemInfo si = new SystemInfo(); + + HardwareAbstractionLayer hal = si.getHardware(); + OperatingSystem os = si.getOperatingSystem(); + + printOperatingSystem(os); + textArea1.append("\n"); + + logger.info("Checking computer system..."); + printComputerSystem(hal.getComputerSystem()); + textArea1.append("\n"); + + logger.info("Checking Processor..."); + printProcessor(hal.getProcessor()); + textArea1.append("\n"); + + logger.info("Checking Memory..."); + printMemory(hal.getMemory()); + textArea1.append("\n"); + + logger.info("Checking CPU..."); + printCpu(hal.getProcessor()); + textArea1.append("\n"); + + logger.info("Checking Processes..."); + printProcesses(os, hal.getMemory()); + textArea1.append("\n"); + + logger.info("Checking Services..."); + printServices(os); + textArea1.append("\n"); + + logger.info("Checking Sensors..."); + printSensors(hal.getSensors()); + textArea1.append("\n"); + + logger.info("Checking Power sources..."); + printPowerSources(hal.getPowerSources()); + textArea1.append("\n"); + + logger.info("Checking Disks..."); + printDisks(hal.getDiskStores()); + textArea1.append("\n"); + + logger.info("Checking Logical Volume Groups ..."); + printLVgroups(hal.getLogicalVolumeGroups()); + textArea1.append("\n"); + + logger.info("Checking File System..."); + printFileSystem(os.getFileSystem()); + textArea1.append("\n"); + + logger.info("Checking Network interfaces..."); + printNetworkInterfaces(hal.getNetworkIFs()); + textArea1.append("\n"); + + logger.info("Checking Network parameters..."); + printNetworkParameters(os.getNetworkParams()); + textArea1.append("\n"); + + logger.info("Checking IP statistics..."); + printInternetProtocolStats(os.getInternetProtocolStats()); + textArea1.append("\n"); + + logger.info("Checking Displays..."); + printDisplays(hal.getDisplays()); + textArea1.append("\n"); + + logger.info("Checking USB Devices..."); + printUsbDevices(hal.getUsbDevices(true)); + textArea1.append("\n"); + + logger.info("Checking Sound Cards..."); + printSoundCards(hal.getSoundCards()); + textArea1.append("\n"); + + logger.info("Checking Graphics Cards..."); + printGraphicsCards(hal.getGraphicsCards()); + + JOptionPane.showMessageDialog(contentPane, "Done!\n", "Finished!", JOptionPane.PLAIN_MESSAGE); + } + + private void onCancel() { + // add your code here if necessary + dispose(); + } + + // all functions codes bellow are copied from oshi-core, and have some changed + private void printOperatingSystem(final OperatingSystem os) { + + ConsoleUtil.consoleOnly(textArea1, String.valueOf(os)); + ConsoleUtil.consoleOnly(textArea1, "Booted: " + Instant.ofEpochSecond(os.getSystemBootTime())); + ConsoleUtil.consoleOnly(textArea1, "Uptime: " + FormatUtil.formatElapsedSecs(os.getSystemUptime())); + ConsoleUtil.consoleOnly(textArea1, "Running with" + (os.isElevated() ? "" : "out") + " elevated permissions."); + ConsoleUtil.consoleOnly(textArea1, "Sessions:"); + for (OSSession s : os.getSessions()) { + ConsoleUtil.consoleOnly(textArea1, " " + s.toString()); + } + } + + private void printComputerSystem(final ComputerSystem computerSystem) { + ConsoleUtil.consoleOnly(textArea1, "System: " + computerSystem.toString()); + ConsoleUtil.consoleOnly(textArea1, " Firmware: " + computerSystem.getFirmware().toString()); + ConsoleUtil.consoleOnly(textArea1, " Baseboard: " + computerSystem.getBaseboard().toString()); + } + + private void printProcessor(CentralProcessor processor) { + ConsoleUtil.consoleOnly(textArea1, processor.toString()); + } + + private void printMemory(GlobalMemory memory) { + ConsoleUtil.consoleOnly(textArea1, "Physical Memory: \n " + memory.toString()); + VirtualMemory vm = memory.getVirtualMemory(); + ConsoleUtil.consoleOnly(textArea1, "Virtual Memory: \n " + vm.toString()); + List pmList = memory.getPhysicalMemory(); + if (!pmList.isEmpty()) { + ConsoleUtil.consoleOnly(textArea1, "Physical Memory: "); + for (PhysicalMemory pm : pmList) { + ConsoleUtil.consoleOnly(textArea1, " " + pm.toString()); + } + } + } + + private void printCpu(CentralProcessor processor) { + ConsoleUtil.consoleOnly(textArea1, "Context Switches/Interrupts: " + processor.getContextSwitches() + " / " + processor.getInterrupts()); + + long[] prevTicks = processor.getSystemCpuLoadTicks(); + long[][] prevProcTicks = processor.getProcessorCpuLoadTicks(); + ConsoleUtil.consoleOnly(textArea1, "CPU, IOWait, and IRQ ticks @ 0 sec:" + Arrays.toString(prevTicks)); + // Wait a second... + Util.sleep(1000); + long[] ticks = processor.getSystemCpuLoadTicks(); + ConsoleUtil.consoleOnly(textArea1, "CPU, IOWait, and IRQ ticks @ 1 sec:" + Arrays.toString(ticks)); + long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()]; + long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()]; + long sys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()]; + long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()]; + long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()]; + long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()]; + long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()]; + long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()]; + long totalCpu = user + nice + sys + idle + iowait + irq + softirq + steal; + + ConsoleUtil.consoleOnly(textArea1, String.format( + "User: %.1f%% Nice: %.1f%% System: %.1f%% Idle: %.1f%% IOwait: %.1f%% IRQ: %.1f%% SoftIRQ: %.1f%% Steal: %.1f%%", + 100d * user / totalCpu, 100d * nice / totalCpu, 100d * sys / totalCpu, 100d * idle / totalCpu, + 100d * iowait / totalCpu, 100d * irq / totalCpu, 100d * softirq / totalCpu, 100d * steal / totalCpu)); + ConsoleUtil.consoleOnly(textArea1, String.format("CPU load: %.1f%%", processor.getSystemCpuLoadBetweenTicks(prevTicks) * 100)); + double[] loadAverage = processor.getSystemLoadAverage(3); + ConsoleUtil.consoleOnly(textArea1, "CPU load averages:" + (loadAverage[0] < 0 ? " N/A" : String.format(" %.2f", loadAverage[0])) + + (loadAverage[1] < 0 ? " N/A" : String.format(" %.2f", loadAverage[1])) + + (loadAverage[2] < 0 ? " N/A" : String.format(" %.2f", loadAverage[2]))); + // per core CPU + StringBuilder procCpu = new StringBuilder("CPU load per processor:"); + double[] load = processor.getProcessorCpuLoadBetweenTicks(prevProcTicks); + for (double avg : load) { + procCpu.append(String.format(" %.1f%%", avg * 100)); + } + ConsoleUtil.consoleOnly(textArea1, procCpu.toString()); + long freq = processor.getProcessorIdentifier().getVendorFreq(); + if (freq > 0) { + ConsoleUtil.consoleOnly(textArea1, "Vendor Frequency: " + FormatUtil.formatHertz(freq)); + } + freq = processor.getMaxFreq(); + if (freq > 0) { + ConsoleUtil.consoleOnly(textArea1, "Max Frequency: " + FormatUtil.formatHertz(freq)); + } + long[] freqs = processor.getCurrentFreq(); + if (freqs[0] > 0) { + StringBuilder sb = new StringBuilder("Current Frequencies: "); + for (int i = 0; i < freqs.length; i++) { + if (i > 0) { + sb.append(", "); + } + sb.append(FormatUtil.formatHertz(freqs[i])); + } + ConsoleUtil.consoleOnly(textArea1, sb.toString()); + } + } + + private void printProcesses(OperatingSystem os, GlobalMemory memory) { + OSProcess myProc = os.getProcess(os.getProcessId()); + // current process will never be null. Other code should check for null here + ConsoleUtil.consoleOnly(textArea1, + "My PID: " + myProc.getProcessID() + " with affinity " + Long.toBinaryString(myProc.getAffinityMask())); + ConsoleUtil.consoleOnly(textArea1, "Processes: " + os.getProcessCount() + ", Threads: " + os.getThreadCount()); + // Sort by highest CPU + List procs = os.getProcesses(OperatingSystem.ProcessFiltering.ALL_PROCESSES, OperatingSystem.ProcessSorting.CPU_DESC, 5); + ConsoleUtil.consoleOnly(textArea1, " PID %CPU %MEM VSZ RSS Name"); + for (int i = 0; i < procs.size() && i < 5; i++) { + OSProcess p = procs.get(i); + ConsoleUtil.consoleOnly(textArea1, String.format(" %5d %5.1f %4.1f %9s %9s %s", p.getProcessID(), + 100d * (p.getKernelTime() + p.getUserTime()) / p.getUpTime(), + 100d * p.getResidentSetSize() / memory.getTotal(), FormatUtil.formatBytes(p.getVirtualSize()), + FormatUtil.formatBytes(p.getResidentSetSize()), p.getName())); + } + OSProcess p = os.getProcess(os.getProcessId()); + ConsoleUtil.consoleOnly(textArea1, "Current process arguments: "); + for (String s : p.getArguments()) { + ConsoleUtil.consoleOnly(textArea1, " " + s); + } + ConsoleUtil.consoleOnly(textArea1, "Current process environment: "); + for (Map.Entry e : p.getEnvironmentVariables().entrySet()) { + ConsoleUtil.consoleOnly(textArea1, " " + e.getKey() + "=" + e.getValue()); + } + } + + private void printServices(OperatingSystem os) { + ConsoleUtil.consoleOnly(textArea1, "Services: "); + ConsoleUtil.consoleOnly(textArea1, " PID State Name"); + // DO 5 each of running and stopped + int i = 0; + for (OSService s : os.getServices()) { + if (s.getState().equals(OSService.State.RUNNING) && i++ < 5) { + ConsoleUtil.consoleOnly(textArea1, String.format(" %5d %7s %s", s.getProcessID(), s.getState(), s.getName())); + } + } + i = 0; + for (OSService s : os.getServices()) { + if (s.getState().equals(OSService.State.STOPPED) && i++ < 5) { + ConsoleUtil.consoleOnly(textArea1, String.format(" %5d %7s %s", s.getProcessID(), s.getState(), s.getName())); + } + } + } + + private void printSensors(Sensors sensors) { + ConsoleUtil.consoleOnly(textArea1, "Sensors: " + sensors.toString()); + } + + private void printPowerSources(List list) { + StringBuilder sb = new StringBuilder("Power Sources: "); + if (list.isEmpty()) { + sb.append("Unknown"); + } + for (PowerSource powerSource : list) { + sb.append("\n ").append(powerSource.toString()); + } + ConsoleUtil.consoleOnly(textArea1, sb.toString()); + } + + private void printDisks(List list) { + ConsoleUtil.consoleOnly(textArea1, "Disks:"); + for (HWDiskStore disk : list) { + ConsoleUtil.consoleOnly(textArea1, " " + disk.toString()); + + List partitions = disk.getPartitions(); + for (HWPartition part : partitions) { + ConsoleUtil.consoleOnly(textArea1, " |-- " + part.toString()); + } + } + + } + + private void printLVgroups(List list) { + if (!list.isEmpty()) { + ConsoleUtil.consoleOnly(textArea1, "Logical Volume Groups:"); + for (LogicalVolumeGroup lvg : list) { + ConsoleUtil.consoleOnly(textArea1, " " + lvg.toString()); + } + } + } + + private void printFileSystem(FileSystem fileSystem) { + ConsoleUtil.consoleOnly(textArea1, "File System:"); + + ConsoleUtil.consoleOnly(textArea1, String.format(" File Descriptors: %d/%d", fileSystem.getOpenFileDescriptors(), + fileSystem.getMaxFileDescriptors())); + + for (OSFileStore fs : fileSystem.getFileStores()) { + long usable = fs.getUsableSpace(); + long total = fs.getTotalSpace(); + ConsoleUtil.consoleOnly(textArea1, String.format( + " %s (%s) [%s] %s of %s free (%.1f%%), %s of %s files free (%.1f%%) is %s " + + (fs.getLogicalVolume() != null && fs.getLogicalVolume().length() > 0 ? "[%s]" : "%s") + + " and is mounted at %s", + fs.getName(), fs.getDescription().isEmpty() ? "file system" : fs.getDescription(), fs.getType(), + FormatUtil.formatBytes(usable), FormatUtil.formatBytes(fs.getTotalSpace()), 100d * usable / total, + FormatUtil.formatValue(fs.getFreeInodes(), ""), FormatUtil.formatValue(fs.getTotalInodes(), ""), + 100d * fs.getFreeInodes() / fs.getTotalInodes(), fs.getVolume(), fs.getLogicalVolume(), + fs.getMount())); + } + } + + private void printNetworkInterfaces(List list) { + StringBuilder sb = new StringBuilder("Network Interfaces:"); + if (list.isEmpty()) { + sb.append(" Unknown"); + } else { + for (NetworkIF net : list) { + sb.append("\n ").append(net.toString()); + } + } + ConsoleUtil.consoleOnly(textArea1, sb.toString()); + } + + private void printNetworkParameters(NetworkParams networkParams) { + ConsoleUtil.consoleOnly(textArea1, "Network parameters:\n " + networkParams.toString()); + } + + private void printInternetProtocolStats(InternetProtocolStats ip) { + ConsoleUtil.consoleOnly(textArea1, "Internet Protocol statistics:"); + ConsoleUtil.consoleOnly(textArea1, " TCPv4: " + ip.getTCPv4Stats()); + ConsoleUtil.consoleOnly(textArea1, " TCPv6: " + ip.getTCPv6Stats()); + ConsoleUtil.consoleOnly(textArea1, " UDPv4: " + ip.getUDPv4Stats()); + ConsoleUtil.consoleOnly(textArea1, " UDPv6: " + ip.getUDPv6Stats()); + } + + private void printDisplays(List list) { + ConsoleUtil.consoleOnly(textArea1, "Displays:"); + int i = 0; + for (Display display : list) { + ConsoleUtil.consoleOnly(textArea1, " Display " + i + ":"); + ConsoleUtil.consoleOnly(textArea1, String.valueOf(display)); + i++; + } + } + + private void printUsbDevices(List list) { + ConsoleUtil.consoleOnly(textArea1, "USB Devices:"); + for (UsbDevice usbDevice : list) { + ConsoleUtil.consoleOnly(textArea1, String.valueOf(usbDevice)); + } + } + + private void printSoundCards(List list) { + ConsoleUtil.consoleOnly(textArea1, "Sound Cards:"); + for (SoundCard card : list) { + ConsoleUtil.consoleOnly(textArea1, " " + String.valueOf(card)); + } + } + + private void printGraphicsCards(List list) { + ConsoleUtil.consoleOnly(textArea1, "Graphics Cards:"); + if (list.isEmpty()) { + ConsoleUtil.consoleOnly(textArea1, " None detected."); + } else { + for (GraphicsCard card : list) { + ConsoleUtil.consoleOnly(textArea1, " " + String.valueOf(card)); + } + } + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + contentPane = new JPanel(); + contentPane.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + final JPanel panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(1, 2, new Insets(0, 0, 10, 10), -1, -1)); + contentPane.add(panel1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, 1, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + panel1.add(spacer1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final JPanel panel2 = new JPanel(); + panel2.setLayout(new GridLayoutManager(1, 2, new Insets(0, 0, 0, 0), -1, -1, true, false)); + panel1.add(panel2, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + buttonOK = new JButton(); + buttonOK.setText("Start"); + panel2.add(buttonOK, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + buttonCancel = new JButton(); + buttonCancel.setText("Cancel"); + panel2.add(buttonCancel, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel3 = new JPanel(); + panel3.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + contentPane.add(panel3, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JScrollPane scrollPane1 = new JScrollPane(); + panel3.add(scrollPane1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + textArea1 = new JTextArea(); + scrollPane1.setViewportView(textArea1); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return contentPane; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/UpdateDialog.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/UpdateDialog.form new file mode 100644 index 0000000..0f7220f --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/UpdateDialog.form @@ -0,0 +1,96 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/UpdateDialog.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/UpdateDialog.java new file mode 100644 index 0000000..a9f9f50 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/UpdateDialog.java @@ -0,0 +1,204 @@ +package io.fluent.pcinfo.ui.dialog; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.StreamProgress; +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.http.HttpUtil; +import com.formdev.flatlaf.util.SystemInfo; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; +import io.fluent.pcinfo.App; +import io.fluent.pcinfo.ui.UiConsts; +import io.fluent.pcinfo.util.ComponentUtil; +import io.fluent.pcinfo.util.ScrollUtil; +import io.fluent.pcinfo.util.SystemUtil; +import io.fluent.pcinfo.util.UpgradeUtil; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.File; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; + +/** + * Update download dialog + * + * @author RememBerBer + * @since 2021/11/08. + */ +public class UpdateDialog extends JDialog { + private static final long serialVersionUID = -5858063892133811698L; + private JPanel contentPane; + private JButton buttonOK; + private JButton buttonCancel; + private JProgressBar progressBarDownload; + private JButton buttonDownloadFromWeb; + private JLabel statusLabel; + private File downLoadFile; + + public UpdateDialog() { + super(App.mainFrame, "Download the new version"); + setContentPane(contentPane); + setModal(true); + getRootPane().setDefaultButton(buttonOK); + + if (SystemUtil.isMacOs() && SystemInfo.isMacFullWindowContentSupported) { + this.getRootPane().putClientProperty("apple.awt.fullWindowContent", true); + this.getRootPane().putClientProperty("apple.awt.transparentTitleBar", true); + this.getRootPane().putClientProperty("apple.awt.fullscreenable", true); + this.getRootPane().putClientProperty("apple.awt.windowTitleVisible", false); + GridLayoutManager gridLayoutManager = (GridLayoutManager) contentPane.getLayout(); + gridLayoutManager.setMargin(new Insets(28, 0, 0, 0)); + } + + ComponentUtil.setPreferSizeAndLocateToCenter(this, 600, 200); + + buttonOK.addActionListener(e -> onOK()); + + buttonCancel.addActionListener(e -> onCancel()); + + // call onCancel() when cross is clicked + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + onCancel(); + } + }); + + // call onCancel() on ESCAPE + contentPane.registerKeyboardAction(e -> onCancel(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + buttonDownloadFromWeb.addActionListener(e -> { + Desktop desktop = Desktop.getDesktop(); + try { + desktop.browse(new URI("https://github.com/rememberber/MooInfo/releases")); + } catch (IOException | URISyntaxException ex) { + ex.printStackTrace(); + } + }); + } + + public void downLoad(String newVersion) { + buttonOK.setEnabled(false); + ThreadUtil.execute( + () -> { + String fileUrl = "http://download.zhoubochina.com/moo/exe/MooInfo-" + newVersion + "-x64-Setup.exe"; + String fileName = FileUtil.getName(fileUrl); + URL url; + try { + url = new URL(fileUrl); + HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); + // Get the appropriate file length + int fileLength = urlConnection.getContentLength(); + progressBarDownload.setMaximum(fileLength); + } catch (IOException e) { + e.printStackTrace(); + } + + File tempDir = new File(FileUtil.getTmpDirPath() + "MooInfo"); + if (!tempDir.exists()) { + tempDir.mkdirs(); + } + FileUtil.clean(tempDir); + downLoadFile = FileUtil.file(tempDir + File.separator + fileName); + HttpUtil.downloadFile(fileUrl, FileUtil.touch(downLoadFile), new StreamProgress() { + + @Override + public void start() { + statusLabel.setText("Start downloading..."); + } + + @Override + public void progress(long progressSize, long totalSize) { + progressBarDownload.setValue((int) progressSize); + statusLabel.setText("Already download:" + FileUtil.readableFileSize(progressSize)); + } + + @Override + public void finish() { + statusLabel.setText("Download finished!"); + buttonOK.setEnabled(true); + } + }); + } + ); + } + + private void onOK() { + try { + Desktop.getDesktop().open(downLoadFile); + dispose(); + System.exit(0); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void onCancel() { + // add your code here if necessary + dispose(); + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + contentPane = new JPanel(); + contentPane.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + final JPanel panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(1, 2, new Insets(0, 0, 10, 10), -1, -1)); + contentPane.add(panel1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, 1, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + panel1.add(spacer1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final JPanel panel2 = new JPanel(); + panel2.setLayout(new GridLayoutManager(1, 3, new Insets(0, 0, 0, 0), -1, -1)); + panel1.add(panel2, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + buttonOK = new JButton(); + buttonOK.setText("Install Now"); + panel2.add(buttonOK, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + buttonCancel = new JButton(); + buttonCancel.setText("Cancel"); + panel2.add(buttonCancel, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + buttonDownloadFromWeb = new JButton(); + buttonDownloadFromWeb.setText("Open Download Page"); + panel2.add(buttonDownloadFromWeb, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel3 = new JPanel(); + panel3.setLayout(new GridLayoutManager(4, 1, new Insets(0, 0, 0, 0), -1, -1)); + contentPane.add(panel3, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + progressBarDownload = new JProgressBar(); + panel3.add(progressBarDownload, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + statusLabel = new JLabel(); + statusLabel.setText("就绪"); + panel3.add(statusLabel, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer2 = new Spacer(); + panel3.add(spacer2, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final Spacer spacer3 = new Spacer(); + panel3.add(spacer3, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return contentPane; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/UpdateInfoDialog.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/UpdateInfoDialog.form new file mode 100644 index 0000000..1a1df6a --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/UpdateInfoDialog.form @@ -0,0 +1,86 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/UpdateInfoDialog.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/UpdateInfoDialog.java new file mode 100644 index 0000000..8c6c703 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/dialog/UpdateInfoDialog.java @@ -0,0 +1,169 @@ +package io.fluent.pcinfo.ui.dialog; + +import com.formdev.flatlaf.util.SystemInfo; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; +import io.fluent.pcinfo.App; +import io.fluent.pcinfo.util.ComponentUtil; +import io.fluent.pcinfo.util.SystemUtil; +import lombok.Getter; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import javax.swing.text.html.HTMLEditorKit; +import javax.swing.text.html.StyleSheet; +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +/** + * Dialog of update info + * + * @author RememBerBer + * @since 2021/11/08. + */ +@Getter +public class UpdateInfoDialog extends JDialog { + private static final long serialVersionUID = -9114988145315865608L; + private JPanel contentPane; + private JButton buttonOK; + private JButton buttonCancel; + private JTextPane textPane1; + private String newVersion; + + public void setNewVersion(String newVersion) { + this.newVersion = newVersion; + } + + public UpdateInfoDialog() { + super(App.mainFrame, "Surprise the new version"); + + setContentPane(contentPane); + setModal(true); + getRootPane().setDefaultButton(buttonOK); + + if (SystemUtil.isMacOs() && SystemInfo.isMacFullWindowContentSupported) { + this.getRootPane().putClientProperty("apple.awt.fullWindowContent", true); + this.getRootPane().putClientProperty("apple.awt.transparentTitleBar", true); + this.getRootPane().putClientProperty("apple.awt.fullscreenable", true); + this.getRootPane().putClientProperty("apple.awt.windowTitleVisible", false); + GridLayoutManager gridLayoutManager = (GridLayoutManager) contentPane.getLayout(); + gridLayoutManager.setMargin(new Insets(28, 0, 0, 0)); + } + + ComponentUtil.setPreferSizeAndLocateToCenter(this, 0.4, 0.64); + + buttonOK.addActionListener(e -> onOK()); + + buttonCancel.addActionListener(e -> onCancel()); + + // call onCancel() when cross is clicked + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + onCancel(); + } + }); + + // call onCancel() on ESCAPE + contentPane.registerKeyboardAction(e -> onCancel(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + } + + private void onOK() { + if (SystemUtil.isMacOs()) { + Desktop desktop = Desktop.getDesktop(); + try { + desktop.browse(new URI("https://github.com/rememberber/MooInfo/releases")); + } catch (IOException | URISyntaxException ex) { + ex.printStackTrace(); + } + } else { + UpdateDialog dialog = new UpdateDialog(); + dialog.pack(); + dialog.downLoad(newVersion); + dialog.setVisible(true); + } + dispose(); + } + + private void onCancel() { + dispose(); + } + + public void setPlaneText(String planeText) { + textPane1.setContentType("text/plain; charset=utf-8"); + textPane1.setText(planeText); + textPane1.setCaretPosition(0); + } + + public void setHtmlText(String htmlText) { + textPane1.setContentType("text/html; charset=utf-8"); + HTMLEditorKit kit = new HTMLEditorKit(); + textPane1.setEditorKit(kit); + StyleSheet styleSheet = kit.getStyleSheet(); + styleSheet.addRule("h2{color:#FBC87A;}"); + styleSheet.addRule("body{font-family:" + buttonOK.getFont().getName() + ";font-size:" + buttonOK.getFont().getSize() + ";}"); + textPane1.setText(htmlText); + textPane1.setCaretPosition(0); + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + contentPane = new JPanel(); + contentPane.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 10, 0), -1, -1)); + final JPanel panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(1, 3, new Insets(0, 0, 10, 0), -1, -1)); + contentPane.add(panel1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, 1, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + panel1.add(spacer1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final JPanel panel2 = new JPanel(); + panel2.setLayout(new GridLayoutManager(1, 3, new Insets(0, 0, 0, 0), -1, -1)); + panel1.add(panel2, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + buttonOK = new JButton(); + buttonOK.setText("Download Now"); + panel2.add(buttonOK, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + buttonCancel = new JButton(); + buttonCancel.setText("Cancel"); + panel2.add(buttonCancel, new GridConstraints(0, 1, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer2 = new Spacer(); + panel1.add(spacer2, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final JPanel panel3 = new JPanel(); + panel3.setLayout(new GridLayoutManager(1, 1, new Insets(10, 0, 0, 0), -1, -1)); + contentPane.add(panel3, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JScrollPane scrollPane1 = new JScrollPane(); + panel3.add(scrollPane1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + scrollPane1.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); + textPane1 = new JTextPane(); + textPane1.setEditable(false); + textPane1.setMargin(new Insets(80, 28, 3, 28)); + textPane1.setText(""); + scrollPane1.setViewportView(textPane1); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return contentPane; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/CpuForm.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/CpuForm.form new file mode 100644 index 0000000..c843346 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/CpuForm.form @@ -0,0 +1,402 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/CpuForm.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/CpuForm.java new file mode 100644 index 0000000..5b9698a --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/CpuForm.java @@ -0,0 +1,520 @@ +package io.fluent.pcinfo.ui.form; + +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; +import io.fluent.pcinfo.ui.Style; +import lombok.Getter; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.data.time.DynamicTimeSeriesCollection; +import org.jfree.data.time.Second; +import oshi.hardware.CentralProcessor; +import oshi.hardware.Sensors; +import io.fluent.pcinfo.App; +import io.fluent.pcinfo.ui.UiConsts; +import io.fluent.pcinfo.util.ComponentUtil; +import io.fluent.pcinfo.util.ScrollUtil; +import io.fluent.pcinfo.util.SystemUtil; +import io.fluent.pcinfo.util.UpgradeUtil; +import javax.swing.*; +import java.awt.*; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.DecimalFormat; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * CpuForm + * + * @author RememBerBer + * @since 2021/11/16. + */ +@Getter +public class CpuForm { + private JPanel mainPanel; + private JProgressBar scuProgressBar; + private JPanel pcuPanel; + private JPanel scuPanel; + private JPanel pcuProgressBarPanel; + private JLabel scuTitleLabel; + private JLabel pcuTitleLabel; + private JTextPane cpuInfoTextPane; + private JPanel panel1; + private JPanel pcfPanel; + private JLabel pcfLabel; + private JLabel usageLabel; + private JLabel freqLabel; + private JLabel InterruptsLabel; + private JLabel contextSwitchesLabel; + private JScrollPane scrollPaneLeft; + private JScrollPane scrollPaneRight; + private JLabel temperatureLabel; + private JLabel voltageLabel; + private JLabel fanSpeedsLabel; + private JSplitPane splitPane; + private JPanel chartPanel; + + private static final Log logger = LogFactory.get(); + + private static CpuForm cpuForm; + + private static long[] prevTicks; + + private static long[][] preProcessorTicks; + + private static List processorProgressBars; + private static List processorTextFields; + + private static DynamicTimeSeriesCollection sysData; + + public static CpuForm getInstance() { + if (cpuForm == null) { + cpuForm = new CpuForm(); + } + return cpuForm; + } + + public static void init() { + cpuForm = getInstance(); + + initUi(); + initCpuInfo(); + + ScheduledExecutorService serviceStartPerSecond = Executors.newSingleThreadScheduledExecutor(); + serviceStartPerSecond.scheduleAtFixedRate(() -> { + initPcuInfo(); + initPcfInfo(); + initIndicatorInfo(); + }, 0, 1, TimeUnit.SECONDS); + + } + + private static void initUi() { + CpuForm cpuForm = getInstance(); + + cpuForm.getSplitPane().setDividerLocation((int) (App.mainFrame.getWidth() * 0.38)); + + Style.emphaticTitleFont(cpuForm.getScuTitleLabel()); + Style.emphaticTitleFont(cpuForm.getPcuTitleLabel()); + Style.emphaticTitleFont(cpuForm.getPcfLabel()); + + Style.emphaticIndicatorFont(cpuForm.getUsageLabel()); + Style.emphaticIndicatorFont(cpuForm.getFreqLabel()); + Style.emphaticIndicatorFont(cpuForm.getInterruptsLabel()); + Style.emphaticIndicatorFont(cpuForm.getContextSwitchesLabel()); + Style.emphaticIndicatorFont(cpuForm.getTemperatureLabel()); + Style.emphaticIndicatorFont(cpuForm.getVoltageLabel()); + Style.emphaticIndicatorFont(cpuForm.getFanSpeedsLabel()); + + ScrollUtil.smoothPane(cpuForm.getScrollPaneLeft()); + ScrollUtil.smoothPane(cpuForm.getScrollPaneRight()); + + Dimension d = new Dimension(-1, 100); + cpuForm.getScuProgressBar().setMinimumSize(d); + + CentralProcessor cpu = App.si.getHardware().getProcessor(); + int logicalProcessorCount = cpu.getLogicalProcessorCount(); + + JPanel pcuProgressBarPanel = cpuForm.getPcuProgressBarPanel(); + pcuProgressBarPanel.setLayout(new GridLayoutManager(logicalProcessorCount, 2, new Insets(0, 0, 0, 0), -1, -1)); + + JPanel pcfPanel = cpuForm.getPcfPanel(); + pcfPanel.setLayout(new GridLayoutManager(logicalProcessorCount, 2, new Insets(0, 0, 0, 0), -1, -1)); + + processorProgressBars = new ArrayList<>(); + processorTextFields = new ArrayList<>(); + for (int i = 0; i < logicalProcessorCount; i++) { + JLabel label = new JLabel(); + label.setText("CPU " + i); + pcuProgressBarPanel.add(label, new GridConstraints(i, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + + JProgressBar progressBar = new JProgressBar(); + pcuProgressBarPanel.add(progressBar, new GridConstraints(i, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + + processorProgressBars.add(progressBar); + + JLabel labelPcf = new JLabel(); + labelPcf.setText("CPU " + i); + pcfPanel.add(labelPcf, new GridConstraints(i, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + + JTextField textField = new JTextField(); + textField.setEditable(false); + textField.setForeground(progressBar.getForeground()); + pcfPanel.add(textField, new GridConstraints(i, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + + processorTextFields.add(textField); + } + + // Codes bellow are copied from oshi demo. + Date date = Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()); + sysData = new DynamicTimeSeriesCollection(1, 60, new Second()); + sysData.setTimeBase(new Second(date)); + sysData.addSeries(floatArrayPercent(cpuData(cpu)), 0, "All cpus"); + + JFreeChart systemCpu = ChartFactory.createTimeSeriesChart(null, null, null, sysData, false, + true, false); + + systemCpu.setBackgroundPaint(cpuForm.getChartPanel().getBackground()); + systemCpu.setAntiAlias(true); + systemCpu.getXYPlot().setDomainGridlinesVisible(false); + systemCpu.getXYPlot().setRangeGridlinesVisible(false); + systemCpu.getXYPlot().setBackgroundPaint(cpuForm.getScuProgressBar().getBackground()); + systemCpu.getXYPlot().setOutlinePaint(cpuForm.getScuProgressBar().getBackground()); + systemCpu.getXYPlot().getRenderer().setSeriesPaint(0, cpuForm.getScuProgressBar().getForeground()); + systemCpu.getXYPlot().getRenderer().setSeriesStroke(0, new BasicStroke(2f)); + systemCpu.getXYPlot().getDomainAxis().setVisible(false); + systemCpu.getXYPlot().getRangeAxis().setVisible(false); + + cpuForm.getChartPanel().setPreferredSize(new Dimension(-1, 100)); + cpuForm.getChartPanel().setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + cpuForm.getChartPanel().add(new ChartPanel(systemCpu), new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, new Dimension(150, 50), null, 0, false)); + + + } + + private static void initCpuInfo() { + CpuForm cpuForm = getInstance(); + JTextPane cpuInfoTextPane = cpuForm.getCpuInfoTextPane(); + String contentType = "text/html; charset=utf-8"; + cpuInfoTextPane.setContentType(contentType); + cpuInfoTextPane.setText(getCpuInfo()); + } + + public static String getCpuInfo() { + StringBuilder builder = new StringBuilder(); + CentralProcessor processor = App.si.getHardware().getProcessor(); + + CentralProcessor.ProcessorIdentifier processorIdentifier = processor.getProcessorIdentifier(); + builder.append("
"); + builder.append("Name: ").append(processorIdentifier.getName()); + builder.append("
Identifier: ").append(processorIdentifier.getIdentifier()); + builder.append("
Micro Architecture: ").append(processorIdentifier.getMicroarchitecture()); + builder.append("
Model: ").append(processorIdentifier.getModel()); + builder.append("
Family: ").append(processorIdentifier.getFamily()); + builder.append("
Processor ID: ").append(processorIdentifier.getProcessorID()); + builder.append("
Vendor: ").append(processorIdentifier.getVendor()); + builder.append("
Vendor Freq: ").append(new BigDecimal(processorIdentifier.getVendorFreq()).divide(new BigDecimal(1000000000), 2, RoundingMode.HALF_UP)).append(" GHz"); + builder.append("
Stepping: ").append(processorIdentifier.getStepping()); + builder.append("
"); + builder.append("
Physical Package Count: ").append(processor.getPhysicalPackageCount()); + builder.append("
Physical Processor Count: ").append(processor.getPhysicalProcessorCount()); + builder.append("
Logical Processor Count: ").append(processor.getLogicalProcessorCount()); + builder.append("
Max Freq: ").append(new BigDecimal(processor.getMaxFreq()).divide(new BigDecimal(1000000000), 2, RoundingMode.HALF_UP)).append(" GHz"); + + return builder.toString(); + + } + + /** + * Codes are copied from Hutool and have some modifications. + */ + private static void initPcuInfo() { + CentralProcessor processor = App.si.getHardware().getProcessor(); + DecimalFormat format = new DecimalFormat("#.00"); + + long[] ticks = processor.getSystemCpuLoadTicks(); + if (prevTicks == null) { + prevTicks = ticks; + } + + long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()]; + long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()]; + long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()]; + long ioWait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()]; + long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()]; + long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()]; + long softIrq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()]; + long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()]; + long totalCpu = Math.max(user + nice + cSys + idle + ioWait + irq + softIrq + steal, 0); + + sysData.advanceTime(); + sysData.appendData(floatArrayPercent(cpuData(processor))); + + prevTicks = ticks; + + double free = Double.parseDouble(format.format(idle <= 0 ? 0 : (100d * idle / totalCpu))); + + double cpuUsage = Double.parseDouble(format.format((100 - free))); + + CpuForm cpuForm = getInstance(); + JProgressBar scuProgressBar = cpuForm.getScuProgressBar(); + scuProgressBar.setMaximum(100); + int cpuUsagePercent = (int) cpuUsage; + scuProgressBar.setValue(cpuUsagePercent); + scuProgressBar.setStringPainted(true); + String cpuUsageStr = cpuUsage + "%"; + scuProgressBar.setString(cpuUsageStr); + cpuForm.getUsageLabel().setText(cpuUsageStr); + + long[][] processorTicks = processor.getProcessorCpuLoadTicks(); + if (preProcessorTicks == null) { + preProcessorTicks = processorTicks; + } + + for (int i = 0; i < processorTicks.length; i++) { + long[] pTicks = processorTicks[i]; + long[] prePTicks = preProcessorTicks[i]; + + long pUser = pTicks[CentralProcessor.TickType.USER.getIndex()] - prePTicks[CentralProcessor.TickType.USER.getIndex()]; + long pNice = pTicks[CentralProcessor.TickType.NICE.getIndex()] - prePTicks[CentralProcessor.TickType.NICE.getIndex()]; + long pCSys = pTicks[CentralProcessor.TickType.SYSTEM.getIndex()] - prePTicks[CentralProcessor.TickType.SYSTEM.getIndex()]; + long pIoWait = pTicks[CentralProcessor.TickType.IOWAIT.getIndex()] - prePTicks[CentralProcessor.TickType.IOWAIT.getIndex()]; + long pIdle = pTicks[CentralProcessor.TickType.IDLE.getIndex()] - prePTicks[CentralProcessor.TickType.IDLE.getIndex()]; + long pIrq = pTicks[CentralProcessor.TickType.IRQ.getIndex()] - prePTicks[CentralProcessor.TickType.IRQ.getIndex()]; + long pSoftIrq = pTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prePTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()]; + long pSteal = pTicks[CentralProcessor.TickType.STEAL.getIndex()] - prePTicks[CentralProcessor.TickType.STEAL.getIndex()]; + long pTotalCpu = Math.max(pUser + pNice + pCSys + pIdle + pIoWait + pIrq + pSoftIrq + pSteal, 0); + + double pFree = Double.parseDouble(format.format(pIdle <= 0 ? 0 : (100d * pIdle / pTotalCpu))); + + double pCpuUsage = Double.parseDouble(format.format((100 - pFree))); + + JProgressBar jProgressBar = processorProgressBars.get(i); + jProgressBar.setMaximum(100); + int pCpuUsagePercent = (int) pCpuUsage; + jProgressBar.setValue(pCpuUsagePercent); + jProgressBar.setStringPainted(true); + jProgressBar.setString(pCpuUsage + "%"); + jProgressBar.setToolTipText(pCpuUsage + "%"); + + } + + preProcessorTicks = processorTicks; + + } + + private static void initPcfInfo() { + CpuForm cpuForm = getInstance(); + CentralProcessor processor = App.si.getHardware().getProcessor(); + + long[] currentFreq = processor.getCurrentFreq(); + BigDecimal totalFreq = BigDecimal.ZERO; + + for (int i = 0; i < currentFreq.length; i++) { + + JTextField textField = processorTextFields.get(i); + BigDecimal divide = new BigDecimal(currentFreq[i]).divide(new BigDecimal(1000000000), 2, RoundingMode.HALF_UP); + String freqStr = divide + " GHz"; + textField.setText(freqStr); + + totalFreq = divide.add(totalFreq); + + } + cpuForm.getFreqLabel().setText(String.valueOf(totalFreq.divide(new BigDecimal(currentFreq.length), 2, RoundingMode.HALF_UP))); + + } + + private static void initIndicatorInfo() { + CpuForm cpuForm = getInstance(); + CentralProcessor processor = App.si.getHardware().getProcessor(); + cpuForm.getInterruptsLabel().setText(String.valueOf(processor.getInterrupts())); + cpuForm.getContextSwitchesLabel().setText(String.valueOf(processor.getContextSwitches())); + + Sensors sensors = App.si.getHardware().getSensors(); + + cpuForm.getTemperatureLabel().setText(String.format("%.1f°C", sensors.getCpuTemperature())); + // Tips are copied from oshi. + cpuForm.getTemperatureLabel().setToolTipText("On Windows, if not running Open Hardware Monitor, \n" + + "requires elevated permissions and hardware BIOS that supports publishing to WMI. \n" + + "In this case, returns the temperature of the \"Thermal Zone\" \n" + + "which may be different than CPU temperature obtained from other sources. \n" + + "In addition, some motherboards may only refresh this value on certain events."); + cpuForm.getVoltageLabel().setText(String.valueOf(sensors.getCpuVoltage())); + cpuForm.getFanSpeedsLabel().setText(Arrays.toString(sensors.getFanSpeeds())); + } + + /** + * Codes are copied from oshi demo. + * + * @param d + * @return + */ + private static float[] floatArrayPercent(double d) { + float[] f = new float[1]; + f[0] = (float) (100d * d); + return f; + } + + /** + * Codes are copied from oshi demo. + * + * @param proc + * @return + */ + private static double cpuData(CentralProcessor proc) { + if (prevTicks == null) { + return 0; + } + double d = proc.getSystemCpuLoadBetweenTicks(prevTicks); + return d; + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + mainPanel = new JPanel(); + mainPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + splitPane = new JSplitPane(); + splitPane.setContinuousLayout(true); + splitPane.setDividerLocation(300); + splitPane.setDividerSize(14); + mainPanel.add(splitPane, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, new Dimension(200, 200), null, 0, false)); + final JPanel panel2 = new JPanel(); + panel2.setLayout(new GridLayoutManager(1, 1, new Insets(10, 10, 10, 0), -1, -1)); + splitPane.setLeftComponent(panel2); + scrollPaneLeft = new JScrollPane(); + panel2.add(scrollPaneLeft, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel3 = new JPanel(); + panel3.setLayout(new GridLayoutManager(5, 1, new Insets(8, 0, 0, 0), -1, -1)); + scrollPaneLeft.setViewportView(panel3); + scuPanel = new JPanel(); + scuPanel.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel3.add(scuPanel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + scuTitleLabel = new JLabel(); + scuTitleLabel.setText("System CPU Usage"); + scuPanel.add(scuTitleLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + scuProgressBar = new JProgressBar(); + scuPanel.add(scuProgressBar, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + pcuPanel = new JPanel(); + pcuPanel.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel3.add(pcuPanel, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + pcuTitleLabel = new JLabel(); + pcuTitleLabel.setText("Processor CPU Usage"); + pcuPanel.add(pcuTitleLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + pcuProgressBarPanel = new JPanel(); + pcuProgressBarPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + pcuPanel.add(pcuProgressBarPanel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel3.add(panel1, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + pcfLabel = new JLabel(); + pcfLabel.setText("Processor CPU Frequency"); + panel1.add(pcfLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + pcfPanel = new JPanel(); + pcfPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + panel1.add(pcfPanel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + panel3.add(spacer1, new GridConstraints(4, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + chartPanel = new JPanel(); + chartPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + panel3.add(chartPanel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JPanel panel4 = new JPanel(); + panel4.setLayout(new GridLayoutManager(3, 1, new Insets(10, 0, 10, 10), -1, -1)); + splitPane.setRightComponent(panel4); + scrollPaneRight = new JScrollPane(); + panel4.add(scrollPaneRight, new GridConstraints(0, 0, 3, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel5 = new JPanel(); + panel5.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1)); + scrollPaneRight.setViewportView(panel5); + final JPanel panel6 = new JPanel(); + panel6.setLayout(new GridLayoutManager(1, 1, new Insets(0, 10, 10, 10), -1, -1)); + panel5.add(panel6, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + cpuInfoTextPane = new JTextPane(); + cpuInfoTextPane.setEditable(true); + panel6.add(cpuInfoTextPane, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel7 = new JPanel(); + panel7.setLayout(new GridLayoutManager(6, 3, new Insets(10, 10, 10, 10), -1, -1)); + panel5.add(panel7, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JPanel panel8 = new JPanel(); + panel8.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1)); + panel7.add(panel8, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JLabel label1 = new JLabel(); + label1.setText("Usage"); + panel8.add(label1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + usageLabel = new JLabel(); + usageLabel.setText("Label"); + panel8.add(usageLabel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel9 = new JPanel(); + panel9.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1)); + panel7.add(panel9, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JLabel label2 = new JLabel(); + label2.setText("Freq"); + panel9.add(label2, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + freqLabel = new JLabel(); + freqLabel.setText("Label"); + panel9.add(freqLabel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel10 = new JPanel(); + panel10.setLayout(new GridLayoutManager(2, 1, new Insets(10, 0, 0, 0), -1, -1)); + panel7.add(panel10, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JLabel label3 = new JLabel(); + label3.setText("Interrupts"); + panel10.add(label3, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + InterruptsLabel = new JLabel(); + InterruptsLabel.setText("Label"); + panel10.add(InterruptsLabel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel11 = new JPanel(); + panel11.setLayout(new GridLayoutManager(2, 1, new Insets(10, 0, 0, 0), -1, -1)); + panel7.add(panel11, new GridConstraints(4, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JLabel label4 = new JLabel(); + label4.setText("Temperature"); + panel11.add(label4, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + temperatureLabel = new JLabel(); + temperatureLabel.setText("Label"); + panel11.add(temperatureLabel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel12 = new JPanel(); + panel12.setLayout(new GridLayoutManager(2, 1, new Insets(10, 0, 0, 0), -1, -1)); + panel7.add(panel12, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JLabel label5 = new JLabel(); + label5.setText("Context Switches"); + panel12.add(label5, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + contextSwitchesLabel = new JLabel(); + contextSwitchesLabel.setText("Label"); + panel12.add(contextSwitchesLabel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel13 = new JPanel(); + panel13.setLayout(new GridLayoutManager(2, 1, new Insets(10, 0, 0, 0), -1, -1)); + panel7.add(panel13, new GridConstraints(4, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JLabel label6 = new JLabel(); + label6.setText("Voltage"); + panel13.add(label6, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + voltageLabel = new JLabel(); + voltageLabel.setText("Label"); + panel13.add(voltageLabel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel14 = new JPanel(); + panel14.setLayout(new GridLayoutManager(2, 1, new Insets(10, 0, 0, 0), -1, -1)); + panel7.add(panel14, new GridConstraints(4, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JLabel label7 = new JLabel(); + label7.setText("Fan Speeds"); + panel14.add(label7, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + fanSpeedsLabel = new JLabel(); + fanSpeedsLabel.setText("Label"); + panel14.add(fanSpeedsLabel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JSeparator separator1 = new JSeparator(); + panel7.add(separator1, new GridConstraints(1, 0, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JSeparator separator2 = new JSeparator(); + panel7.add(separator2, new GridConstraints(3, 0, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JSeparator separator3 = new JSeparator(); + panel7.add(separator3, new GridConstraints(5, 0, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return mainPanel; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/CpuFormLayoutDesign.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/CpuFormLayoutDesign.form new file mode 100644 index 0000000..ad59af4 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/CpuFormLayoutDesign.form @@ -0,0 +1,221 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/CpuFormLayoutDesign.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/CpuFormLayoutDesign.java new file mode 100644 index 0000000..805cc79 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/CpuFormLayoutDesign.java @@ -0,0 +1,148 @@ +package io.fluent.pcinfo.ui.form; + +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; +import lombok.Getter; + +import javax.swing.*; +import java.awt.*; + +/** + * CpuForm + * + * @author RememBerBer + * @since 2021/11/16. + */ +@Getter +public class CpuFormLayoutDesign { + private JPanel mainPanel; + private JProgressBar scuProgressBar; + private JProgressBar progressBar2; + private JProgressBar progressBar3; + private JProgressBar progressBar4; + private JPanel pcuProgressBarPanel; + private JPanel panel1; + private JTextField textField1; + + private static final Log logger = LogFactory.get(); + + private static CpuFormLayoutDesign cpuForm; + + public static CpuFormLayoutDesign getInstance() { + if (cpuForm == null) { + cpuForm = new CpuFormLayoutDesign(); + } + return cpuForm; + } + + public static void init() { + cpuForm = getInstance(); + + initUi(); + initInfo(); + } + + private static void initUi() { + } + + private static void initInfo() { + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + mainPanel = new JPanel(); + mainPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + final JSplitPane splitPane1 = new JSplitPane(); + splitPane1.setDividerLocation(300); + mainPanel.add(splitPane1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, new Dimension(200, 200), null, 0, false)); + final JPanel panel2 = new JPanel(); + panel2.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + splitPane1.setLeftComponent(panel2); + final JScrollPane scrollPane1 = new JScrollPane(); + panel2.add(scrollPane1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel3 = new JPanel(); + panel3.setLayout(new GridLayoutManager(4, 1, new Insets(0, 0, 0, 0), -1, -1)); + scrollPane1.setViewportView(panel3); + final JPanel panel4 = new JPanel(); + panel4.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel3.add(panel4, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JLabel label1 = new JLabel(); + label1.setText("System CPU Usage"); + panel4.add(label1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + scuProgressBar = new JProgressBar(); + panel4.add(scuProgressBar, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel5 = new JPanel(); + panel5.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel3.add(panel5, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JLabel label2 = new JLabel(); + label2.setText("Processor CPU Usage"); + panel5.add(label2, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + pcuProgressBarPanel = new JPanel(); + pcuProgressBarPanel.setLayout(new GridLayoutManager(3, 2, new Insets(0, 0, 0, 0), -1, -1)); + panel5.add(pcuProgressBarPanel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + progressBar2 = new JProgressBar(); + pcuProgressBarPanel.add(progressBar2, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + progressBar3 = new JProgressBar(); + pcuProgressBarPanel.add(progressBar3, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + progressBar4 = new JProgressBar(); + pcuProgressBarPanel.add(progressBar4, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label3 = new JLabel(); + label3.setText("CPU0"); + pcuProgressBarPanel.add(label3, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label4 = new JLabel(); + label4.setText("CPU1"); + pcuProgressBarPanel.add(label4, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label5 = new JLabel(); + label5.setText("CPU2"); + pcuProgressBarPanel.add(label5, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel6 = new JPanel(); + panel6.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel3.add(panel6, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JLabel label6 = new JLabel(); + label6.setText("Processor CPU Frequency"); + panel6.add(label6, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(3, 2, new Insets(0, 0, 0, 0), -1, -1)); + panel6.add(panel1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JLabel label7 = new JLabel(); + label7.setText("CPU0"); + panel1.add(label7, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label8 = new JLabel(); + label8.setText("CPU1"); + panel1.add(label8, new GridConstraints(1, 0, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label9 = new JLabel(); + label9.setText("CPU2"); + panel1.add(label9, new GridConstraints(2, 0, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + textField1 = new JTextField(); + panel1.add(textField1, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false)); + final Spacer spacer1 = new Spacer(); + panel3.add(spacer1, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel7 = new JPanel(); + panel7.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + splitPane1.setRightComponent(panel7); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return mainPanel; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/DetailForm.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/DetailForm.form new file mode 100644 index 0000000..003a219 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/DetailForm.form @@ -0,0 +1,299 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/DetailForm.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/DetailForm.java new file mode 100644 index 0000000..84d1194 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/DetailForm.java @@ -0,0 +1,417 @@ +package io.fluent.pcinfo.ui.form; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.unit.DataSizeUtil; +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.formdev.flatlaf.extras.FlatSVGIcon; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; +import io.fluent.pcinfo.App; +import io.fluent.pcinfo.ui.Style; +import io.fluent.pcinfo.util.DateTimeUtil; +import io.fluent.pcinfo.util.ScrollUtil; +import lombok.Getter; +import oshi.hardware.*; +import oshi.software.os.NetworkParams; +import oshi.software.os.OperatingSystem; +import oshi.util.FormatUtil; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import java.awt.*; +import java.util.Arrays; +import java.util.List; + +/** + * DetailForm + * + * @author RememBerBer + * @since 2021/11/12. + */ +@Getter +public class DetailForm { + private JPanel mainPanel; + private JTextPane osTextPane; + private JLabel osLabel; + private JTextPane computerTextPane; + private JLabel computerLabel; + private JLabel baseBoardLabel; + private JTextPane baseBoardTextPane; + private JTextPane cpuTextPane; + private JLabel cpuLabel; + private JLabel memoryLabel; + private JTextPane memoryTextPane; + private JTextPane storageTextPane; + private JLabel storageLabel; + private JTextPane graphicsCardTextPane; + private JLabel graphicsCardLabel; + private JLabel displayLabel; + private JTextPane displayTextPane; + private JTextPane soundCardTextPane; + private JLabel soundCardLabel; + private JTextPane networkTextPane; + private JLabel networkLabel; + private JTextPane powerSourceTextPane; + private JLabel powerSourceLabel; + private JScrollPane scrollPane; + + private static final Log logger = LogFactory.get(); + + private static DetailForm detailForm; + + public static DetailForm getInstance() { + if (detailForm == null) { + detailForm = new DetailForm(); + } + return detailForm; + } + + public static void init() { + detailForm = getInstance(); + + initUi(); + initInfo(); + } + + private static void initUi() { + DetailForm detailForm = getInstance(); + + ScrollUtil.smoothPane(detailForm.scrollPane); + + Style.emphaticTitleFont(detailForm.getOsLabel()); + Style.emphaticTitleFont(detailForm.getComputerLabel()); + Style.emphaticTitleFont(detailForm.getBaseBoardLabel()); + Style.emphaticTitleFont(detailForm.getCpuLabel()); + Style.emphaticTitleFont(detailForm.getMemoryLabel()); + Style.emphaticTitleFont(detailForm.getStorageLabel()); + Style.emphaticTitleFont(detailForm.getGraphicsCardLabel()); + Style.emphaticTitleFont(detailForm.getDisplayLabel()); + Style.emphaticTitleFont(detailForm.getSoundCardLabel()); + Style.emphaticTitleFont(detailForm.getNetworkLabel()); + Style.emphaticTitleFont(detailForm.getPowerSourceLabel()); + + detailForm.getOsLabel().setIcon(new FlatSVGIcon("icons/system.svg")); + detailForm.getComputerLabel().setIcon(new FlatSVGIcon("icons/firmware.svg")); + detailForm.getCpuLabel().setIcon(new FlatSVGIcon("icons/cpu.svg")); + detailForm.getMemoryLabel().setIcon(new FlatSVGIcon("icons/memory.svg")); + detailForm.getGraphicsCardLabel().setIcon(new FlatSVGIcon("icons/graphicsCard.svg")); + detailForm.getBaseBoardLabel().setIcon(new FlatSVGIcon("icons/chip.svg")); + detailForm.getStorageLabel().setIcon(new FlatSVGIcon("icons/storage.svg")); + detailForm.getDisplayLabel().setIcon(new FlatSVGIcon("icons/display.svg")); + detailForm.getSoundCardLabel().setIcon(new FlatSVGIcon("icons/sound.svg")); + detailForm.getNetworkLabel().setIcon(new FlatSVGIcon("icons/network.svg")); + detailForm.getPowerSourceLabel().setIcon(new FlatSVGIcon("icons/battery.svg")); + + String contentType = "text/html; charset=utf-8"; + detailForm.getOsTextPane().setContentType(contentType); + detailForm.getComputerTextPane().setContentType(contentType); + detailForm.getBaseBoardTextPane().setContentType(contentType); + detailForm.getCpuTextPane().setContentType(contentType); + detailForm.getMemoryTextPane().setContentType(contentType); + detailForm.getStorageTextPane().setContentType(contentType); + detailForm.getGraphicsCardTextPane().setContentType(contentType); + detailForm.getDisplayTextPane().setContentType(contentType); + detailForm.getSoundCardTextPane().setContentType(contentType); + detailForm.getNetworkTextPane().setContentType(contentType); + detailForm.getPowerSourceTextPane().setContentType(contentType); + } + + private static void initInfo() { + DetailForm detailForm = getInstance(); + + HardwareAbstractionLayer hardware = App.si.getHardware(); + + detailForm.getOsTextPane().setText(getOsInfo()); + detailForm.getComputerTextPane().setText(getComputerInfo()); + detailForm.getBaseBoardTextPane().setText(getBaseBoardInfo()); + detailForm.getCpuTextPane().setText(CpuForm.getCpuInfo()); + detailForm.getMemoryTextPane().setText(MemoryForm.getMemoryInfo()); + detailForm.getStorageTextPane().setText(getStorageInfo()); + detailForm.getGraphicsCardTextPane().setText(getGraphicsCardsInfo()); + detailForm.getDisplayTextPane().setText(getDisplayInfo()); + detailForm.getSoundCardTextPane().setText(getSoundCardsInfo()); + detailForm.getNetworkTextPane().setText(getNetworkInfo()); + detailForm.getPowerSourceTextPane().setText(PowerSourceForm.getPowerInfoText(hardware.getPowerSources())); + } + + private static String getOsInfo() { + StringBuilder builder = new StringBuilder(); + OperatingSystem operatingSystem = App.si.getOperatingSystem(); + + builder.append("Manufacturer: ").append(operatingSystem.getManufacturer()); + builder.append("
Family: ").append(operatingSystem.getFamily()); + builder.append("
Version: ").append(operatingSystem.getVersionInfo()); + builder.append("
Bitness: ").append(operatingSystem.getBitness()); + builder.append("
"); + builder.append("
Max File Descriptors: ").append(operatingSystem.getFileSystem().getMaxFileDescriptors()); + builder.append("
Open File Descriptors: ").append(operatingSystem.getFileSystem().getOpenFileDescriptors()); + builder.append("
Thread Count: ").append(operatingSystem.getThreadCount()); + builder.append("
Process Count: ").append(operatingSystem.getProcessCount()); + builder.append("
System Boot Time: ").append(DateTimeUtil.toReadableTime(operatingSystem.getSystemBootTime() * 1000)); + builder.append("
System Uptime: ").append(DateTimeUtil.toReadableTime(operatingSystem.getSystemUptime())); + + return builder.toString(); + } + + private static String getComputerInfo() { + StringBuilder builder = new StringBuilder(); + ComputerSystem computerSystem = App.si.getHardware().getComputerSystem(); + + builder.append("Manufacturer: ").append(computerSystem.getManufacturer()); + builder.append("
Model: ").append(computerSystem.getModel()); + builder.append("
Serial Number: ").append(computerSystem.getSerialNumber()); + builder.append("
Hardware UUID: ").append(computerSystem.getHardwareUUID()); + builder.append("
"); + builder.append("
Firmware Manufacturer: ").append(computerSystem.getFirmware().getManufacturer()); + builder.append("
Firmware Name: ").append(computerSystem.getFirmware().getName()); + builder.append("
Firmware Description: ").append(computerSystem.getFirmware().getDescription()); + builder.append("
Firmware Version: ").append(computerSystem.getFirmware().getVersion()); + builder.append("
Firmware Release Date: ").append(computerSystem.getFirmware().getReleaseDate()); + + return builder.toString(); + } + + private static String getBaseBoardInfo() { + StringBuilder builder = new StringBuilder(); + Baseboard baseboard = App.si.getHardware().getComputerSystem().getBaseboard(); + + builder.append("Manufacturer: ").append(baseboard.getManufacturer()); + builder.append("
Model: ").append(baseboard.getModel()); + builder.append("
Version: ").append(baseboard.getVersion()); + builder.append("
SerialNumber: ").append(baseboard.getSerialNumber()); + + return builder.toString(); + } + + private static String getStorageInfo() { + StringBuilder builder = new StringBuilder(); + List diskStores = App.si.getHardware().getDiskStores(); + for (int i = 0; i < diskStores.size(); i++) { + HWDiskStore hwDiskStore = diskStores.get(i); + + builder.append("Disk Store: #").append(i); + builder.append("
Name: ").append(hwDiskStore.getName()); + builder.append("
Model: ").append(hwDiskStore.getModel()); + builder.append("
Serial: ").append(hwDiskStore.getSerial()); + builder.append("
Size: ").append(DataSizeUtil.format(hwDiskStore.getSize())); + builder.append("
Partitions: "); + for (HWPartition partition : hwDiskStore.getPartitions()) { + builder.append("
"); + builder.append(partition.toString()); + } + + builder.append("
"); + builder.append("
"); + + } + + return builder.toString(); + } + + private static String getGraphicsCardsInfo() { + StringBuilder builder = new StringBuilder(); + List graphicsCards = App.si.getHardware().getGraphicsCards(); + + for (int i = 0; i < graphicsCards.size(); i++) { + GraphicsCard graphicsCard = graphicsCards.get(i); + + builder.append("Graphics Card: #").append(i); + builder.append("
Name: ").append(graphicsCard.getName()); + builder.append("
Vendor: ").append(graphicsCard.getVendor()); + builder.append("
Version: ").append(graphicsCard.getVersionInfo()); + builder.append("
Device Id: ").append(graphicsCard.getDeviceId()); + builder.append("
VRam: ").append(DataSizeUtil.format(graphicsCard.getVRam())); + builder.append("
"); + builder.append("
"); + } + + return builder.toString(); + } + + private static String getDisplayInfo() { + StringBuilder builder = new StringBuilder(); + List displays = App.si.getHardware().getDisplays(); + + for (int i = 0; i < displays.size(); i++) { + Display display = displays.get(i); + + builder.append("Display: #").append(i); + builder.append("
"); + builder.append(display.toString().replaceAll("\n", "
")); + builder.append("
"); + builder.append("
"); + } + + return builder.toString(); + } + + private static String getSoundCardsInfo() { + StringBuilder builder = new StringBuilder(); + List soundCards = App.si.getHardware().getSoundCards(); + + for (int i = 0; i < soundCards.size(); i++) { + SoundCard soundCard = soundCards.get(i); + + builder.append("SoundCard: #").append(i); + builder.append("
Name: ").append(soundCard.getName()); + builder.append("
Codec: ").append(soundCard.getCodec()); + builder.append("
Driver Version: ").append(soundCard.getDriverVersion()); + + builder.append("
"); + builder.append("
"); + } + + return builder.toString(); + } + + private static String getNetworkInfo() { + StringBuilder builder = new StringBuilder(); + NetworkParams networkParams = App.si.getOperatingSystem().getNetworkParams(); + builder.append("Domain Name: ").append(networkParams.getDomainName()); + builder.append("
Host Name: ").append(networkParams.getHostName()); + builder.append("
Ipv4 Default Gateway: ").append(networkParams.getIpv4DefaultGateway()); + builder.append("
Ipv6 Default Gateway: ").append(networkParams.getIpv6DefaultGateway()); + builder.append("
Dns Servers: ").append(Arrays.toString(networkParams.getDnsServers())); + builder.append("
"); + builder.append("
"); + + List networkIFs = App.si.getHardware().getNetworkIFs(true); + + for (int i = 0; i < networkIFs.size(); i++) { + NetworkIF networkIF = networkIFs.get(i); + + builder.append("Network Interface: #").append(i); + builder.append("
"); + builder.append(networkIF.toString().replaceAll("\n", "
")); + builder.append("
"); + builder.append("
"); + } + + return builder.toString(); + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + mainPanel = new JPanel(); + mainPanel.setLayout(new GridLayoutManager(1, 1, new Insets(10, 10, 10, 10), -1, -1)); + scrollPane = new JScrollPane(); + mainPanel.add(scrollPane, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + scrollPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); + final JPanel panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(12, 1, new Insets(0, 0, 0, 0), -1, -1)); + scrollPane.setViewportView(panel1); + final JPanel panel2 = new JPanel(); + panel2.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel1.add(panel2, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + osLabel = new JLabel(); + osLabel.setText("Operating System"); + panel2.add(osLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + osTextPane = new JTextPane(); + panel2.add(osTextPane, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel3 = new JPanel(); + panel3.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel1.add(panel3, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + computerLabel = new JLabel(); + computerLabel.setText("Computer"); + panel3.add(computerLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + computerTextPane = new JTextPane(); + panel3.add(computerTextPane, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel4 = new JPanel(); + panel4.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel1.add(panel4, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + baseBoardLabel = new JLabel(); + baseBoardLabel.setText("Base Board"); + panel4.add(baseBoardLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + baseBoardTextPane = new JTextPane(); + panel4.add(baseBoardTextPane, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel5 = new JPanel(); + panel5.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel1.add(panel5, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + cpuLabel = new JLabel(); + cpuLabel.setText("CPU"); + panel5.add(cpuLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + cpuTextPane = new JTextPane(); + panel5.add(cpuTextPane, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel6 = new JPanel(); + panel6.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel1.add(panel6, new GridConstraints(4, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + memoryLabel = new JLabel(); + memoryLabel.setText("Memory"); + panel6.add(memoryLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + memoryTextPane = new JTextPane(); + panel6.add(memoryTextPane, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel7 = new JPanel(); + panel7.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel1.add(panel7, new GridConstraints(5, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + storageLabel = new JLabel(); + storageLabel.setText("Storage"); + panel7.add(storageLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + storageTextPane = new JTextPane(); + panel7.add(storageTextPane, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel8 = new JPanel(); + panel8.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel1.add(panel8, new GridConstraints(6, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + graphicsCardLabel = new JLabel(); + graphicsCardLabel.setText("Graphics Card"); + panel8.add(graphicsCardLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + graphicsCardTextPane = new JTextPane(); + panel8.add(graphicsCardTextPane, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel9 = new JPanel(); + panel9.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel1.add(panel9, new GridConstraints(7, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + displayLabel = new JLabel(); + displayLabel.setText("Display"); + panel9.add(displayLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + displayTextPane = new JTextPane(); + panel9.add(displayTextPane, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel10 = new JPanel(); + panel10.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel1.add(panel10, new GridConstraints(8, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + soundCardLabel = new JLabel(); + soundCardLabel.setText("Sound Card"); + panel10.add(soundCardLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + soundCardTextPane = new JTextPane(); + panel10.add(soundCardTextPane, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel11 = new JPanel(); + panel11.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel1.add(panel11, new GridConstraints(9, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + networkLabel = new JLabel(); + networkLabel.setText("Network"); + panel11.add(networkLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + networkTextPane = new JTextPane(); + panel11.add(networkTextPane, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel12 = new JPanel(); + panel12.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel1.add(panel12, new GridConstraints(10, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + powerSourceLabel = new JLabel(); + powerSourceLabel.setText("Power Source"); + panel12.add(powerSourceLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + powerSourceTextPane = new JTextPane(); + panel12.add(powerSourceTextPane, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + panel1.add(spacer1, new GridConstraints(11, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return mainPanel; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/DiskForm.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/DiskForm.form new file mode 100644 index 0000000..bb84116 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/DiskForm.form @@ -0,0 +1,39 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/DiskForm.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/DiskForm.java new file mode 100644 index 0000000..c986de9 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/DiskForm.java @@ -0,0 +1,150 @@ +package io.fluent.pcinfo.ui.form; + +import cn.hutool.core.io.unit.DataSizeUtil; +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; +import io.fluent.pcinfo.App; +import io.fluent.pcinfo.util.ScrollUtil; +import lombok.Getter; +import oshi.PlatformEnum; +import oshi.SystemInfo; +import oshi.software.os.FileSystem; +import oshi.software.os.OSFileStore; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import java.awt.*; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * DiskForm + * + * @author RememBerBer + * @since 2021/11/15. + */ +@Getter +public class DiskForm { + private JPanel mainPanel; + private JPanel diskListPanel; + private JScrollPane scrollPane; + + private static final Log logger = LogFactory.get(); + + private static DiskForm diskForm; + + public static DiskForm getInstance() { + if (diskForm == null) { + diskForm = new DiskForm(); + } + return diskForm; + } + + public static void init() { + diskForm = getInstance(); + + initUi(); + + ScheduledExecutorService serviceStartPerSecond = Executors.newSingleThreadScheduledExecutor(); + serviceStartPerSecond.scheduleAtFixedRate(DiskForm::initInfo, 0, 10, TimeUnit.SECONDS); + } + + private static void initUi() { + ScrollUtil.smoothPane(getInstance().getScrollPane()); + } + + private static void initInfo() { + FileSystem fileSystem = App.si.getOperatingSystem().getFileSystem(); + List fileStores = fileSystem.getFileStores(); + JPanel diskListPanel = getInstance().getDiskListPanel(); + + diskListPanel.removeAll(); + + diskListPanel.setLayout(new GridLayoutManager(fileStores.size() + 1, 1, new Insets(0, 10, 0, 10), -1, -1)); + + for (int i = 0; i < fileStores.size(); i++) { + OSFileStore store = fileStores.get(i); + + JPanel diskPanel = new JPanel(); + diskPanel.setLayout(new GridLayoutManager(3, 3, new Insets(10, 0, 10, 0), -1, -1)); + JLabel title = new JLabel(); + StringBuilder titleBuilder = new StringBuilder(); + titleBuilder.append(store.getName()); + if (SystemInfo.getCurrentPlatform().equals(PlatformEnum.WINDOWS)) { + titleBuilder.append(" - "); + titleBuilder.append(store.getLabel()); + } + title.setText(titleBuilder.toString()); + Font font = new Font(diskListPanel.getFont().getName(), Font.BOLD, diskListPanel.getFont().getSize() + 2); + title.setFont(font); + + diskPanel.add(title, new GridConstraints(0, 0, 1, 3, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + + JProgressBar spacePercent = new JProgressBar(); + diskPanel.add(spacePercent, new GridConstraints(1, 0, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + + long usable = store.getUsableSpace(); + long total = store.getTotalSpace(); + spacePercent.setMaximum(100); + int usagePercent = (int) ((total - usable) * 100 / total); + spacePercent.setValue(usagePercent); + spacePercent.setToolTipText(usagePercent + "%"); + + JLabel used = new JLabel(); + used.setText("Used " + DataSizeUtil.format(total - usable) + "/" + DataSizeUtil.format(total)); + diskPanel.add(used, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + + JLabel available = new JLabel(); + available.setText(DataSizeUtil.format(usable) + "/" + DataSizeUtil.format(total) + " Available"); + diskPanel.add(available, new GridConstraints(2, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + diskPanel.add(spacer1, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + + diskListPanel.add(diskPanel, new GridConstraints(i, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + } + + final Spacer spacer1 = new Spacer(); + diskListPanel.add(spacer1, new GridConstraints(fileStores.size(), 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + mainPanel = new JPanel(); + mainPanel.setLayout(new GridLayoutManager(1, 1, new Insets(10, 10, 10, 10), -1, -1)); + final JPanel panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(1, 1, new Insets(10, 10, 10, 10), -1, -1)); + mainPanel.add(panel1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + scrollPane = new JScrollPane(); + panel1.add(scrollPane, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + scrollPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); + diskListPanel = new JPanel(); + diskListPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + scrollPane.setViewportView(diskListPanel); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return mainPanel; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/DiskFormLayoutDesign.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/DiskFormLayoutDesign.form new file mode 100644 index 0000000..e1d3ab4 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/DiskFormLayoutDesign.form @@ -0,0 +1,154 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/DiskFormLayoutDesign.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/DiskFormLayoutDesign.java new file mode 100644 index 0000000..9d68258 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/DiskFormLayoutDesign.java @@ -0,0 +1,137 @@ +package io.fluent.pcinfo.ui.form; + +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; +import lombok.Getter; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import java.awt.*; + +/** + * DiskForm + * + * @author RememBerBer + * @since 2021/11/15. + */ +@Getter +public class DiskFormLayoutDesign { + private JPanel mainPanel; + private JProgressBar disk1ProgressBar; + private JProgressBar disk2ProgressBar; + private JProgressBar disk3ProgressBar; + private JPanel disk1Panel; + private JLabel disk1Label1; + private JLabel disk1Label2; + private JPanel disk2Panel; + private JLabel disk2Label1; + private JLabel disk2Label2; + private JPanel disk3Panel; + private JLabel disk3Label1; + private JLabel disk3Label2; + private JPanel diskListPanel; + private JLabel disk1Label3; + + private static final Log logger = LogFactory.get(); + + private static DiskFormLayoutDesign diskForm; + + public static DiskFormLayoutDesign getInstance() { + if (diskForm == null) { + diskForm = new DiskFormLayoutDesign(); + } + return diskForm; + } + + public static void init() { + diskForm = getInstance(); + + initUi(); + initInfo(); + } + + private static void initUi() { + } + + private static void initInfo() { + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + mainPanel = new JPanel(); + mainPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + final JPanel panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(1, 1, new Insets(10, 10, 10, 10), -1, -1)); + mainPanel.add(panel1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JScrollPane scrollPane1 = new JScrollPane(); + panel1.add(scrollPane1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + scrollPane1.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); + diskListPanel = new JPanel(); + diskListPanel.setLayout(new GridLayoutManager(4, 1, new Insets(0, 10, 0, 10), -1, -1)); + scrollPane1.setViewportView(diskListPanel); + disk1Panel = new JPanel(); + disk1Panel.setLayout(new GridLayoutManager(3, 3, new Insets(10, 0, 10, 0), -1, -1)); + diskListPanel.add(disk1Panel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + disk1Label1 = new JLabel(); + disk1Label1.setText("Label"); + disk1Panel.add(disk1Label1, new GridConstraints(0, 0, 1, 3, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + disk1ProgressBar = new JProgressBar(); + disk1Panel.add(disk1ProgressBar, new GridConstraints(1, 0, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + disk1Label2 = new JLabel(); + disk1Label2.setText("Label"); + disk1Panel.add(disk1Label2, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + disk1Label3 = new JLabel(); + disk1Label3.setText("Label"); + disk1Panel.add(disk1Label3, new GridConstraints(2, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + disk1Panel.add(spacer1, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + disk2Panel = new JPanel(); + disk2Panel.setLayout(new GridLayoutManager(3, 1, new Insets(10, 0, 10, 0), -1, -1)); + diskListPanel.add(disk2Panel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + disk2Label1 = new JLabel(); + disk2Label1.setText("Label"); + disk2Panel.add(disk2Label1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + disk2ProgressBar = new JProgressBar(); + disk2Panel.add(disk2ProgressBar, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + disk2Label2 = new JLabel(); + disk2Label2.setText("Label"); + disk2Panel.add(disk2Label2, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + disk3Panel = new JPanel(); + disk3Panel.setLayout(new GridLayoutManager(3, 1, new Insets(10, 0, 10, 0), -1, -1)); + diskListPanel.add(disk3Panel, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + disk3Label1 = new JLabel(); + disk3Label1.setText("Label"); + disk3Panel.add(disk3Label1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + disk3ProgressBar = new JProgressBar(); + disk3Panel.add(disk3ProgressBar, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + disk3Label2 = new JLabel(); + disk3Label2.setText("Label"); + disk3Panel.add(disk3Label2, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer2 = new Spacer(); + diskListPanel.add(spacer2, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return mainPanel; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/LoadingForm.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/LoadingForm.form new file mode 100644 index 0000000..811d6cf --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/LoadingForm.form @@ -0,0 +1,24 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/LoadingForm.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/LoadingForm.java new file mode 100644 index 0000000..1c0aac2 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/LoadingForm.java @@ -0,0 +1,78 @@ +package io.fluent.pcinfo.ui.form; + +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import lombok.Getter; + +import javax.swing.*; +import javax.swing.plaf.FontUIResource; +import javax.swing.text.StyleContext; +import java.awt.*; +import java.util.Locale; + +/** + * the loading form + * + * @author RememBerBer + * @since 2021/11/10. + */ +@Getter +public class LoadingForm { + private JPanel loadingPanel; + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + loadingPanel = new JPanel(); + loadingPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + final JLabel label1 = new JLabel(); + Font label1Font = this.$$$getFont$$$(null, -1, 26, label1.getFont()); + if (label1Font != null) label1.setFont(label1Font); + label1.setHorizontalAlignment(10); + label1.setIcon(new ImageIcon(getClass().getResource("/icons/loading_dark.gif"))); + label1.setText("Loading……"); + loadingPanel.add(label1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + } + + /** + * @noinspection ALL + */ + private Font $$$getFont$$$(String fontName, int style, int size, Font currentFont) { + if (currentFont == null) return null; + String resultName; + if (fontName == null) { + resultName = currentFont.getName(); + } else { + Font testFont = new Font(fontName, Font.PLAIN, 10); + if (testFont.canDisplay('a') && testFont.canDisplay('1')) { + resultName = fontName; + } else { + resultName = currentFont.getName(); + } + } + Font font = new Font(resultName, style >= 0 ? style : currentFont.getStyle(), size >= 0 ? size : currentFont.getSize()); + boolean isMac = System.getProperty("os.name", "").toLowerCase(Locale.ENGLISH).startsWith("mac"); + Font fontWithFallback = isMac ? new Font(font.getFamily(), font.getStyle(), font.getSize()) : new StyleContext().getFont(font.getFamily(), font.getStyle(), font.getSize()); + return fontWithFallback instanceof FontUIResource ? fontWithFallback : new FontUIResource(fontWithFallback); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return loadingPanel; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/MainWindow.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/MainWindow.form new file mode 100644 index 0000000..1a6744a --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/MainWindow.form @@ -0,0 +1,116 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/MainWindow.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/MainWindow.java new file mode 100644 index 0000000..1172970 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/MainWindow.java @@ -0,0 +1,126 @@ +package io.fluent.pcinfo.ui.form; + +import com.formdev.flatlaf.util.SystemInfo; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import io.fluent.pcinfo.util.SystemUtil; +import lombok.Getter; + +import javax.swing.*; +import java.awt.*; + +/** + * The main interface + * + * @author RememBerBer + * @since 2021/11/10. + */ +@Getter +public class MainWindow { + private JTabbedPane tabbedPane; + private JPanel mainPanel; + private JPanel overviewPanel; + private JPanel networkPanel; + private JPanel detailPanel; + private JPanel usbPanel; + private JPanel VariablesPanel; + private JPanel processesPanel; + private JPanel diskPanel; + private JPanel memoryPanel; + private JPanel cpuPanel; + private JPanel powerPanel; + + private static MainWindow mainWindow; + + private MainWindow() { + } + + public static MainWindow getInstance() { + if (mainWindow == null) { + mainWindow = new MainWindow(); + } + return mainWindow; + } + + private static GridConstraints gridConstraints = new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, new Dimension(200, 200), null, 0, false); + + public void init() { + mainWindow = getInstance(); + if (SystemUtil.isMacOs() && SystemInfo.isMacFullWindowContentSupported) { + GridLayoutManager gridLayoutManager = (GridLayoutManager) mainPanel.getLayout(); + gridLayoutManager.setMargin(new Insets(25, 0, 0, 0)); + } + + mainWindow.getOverviewPanel().add(OverviewForm.getInstance().getMainPanel(), gridConstraints); + mainWindow.getDetailPanel().add(DetailForm.getInstance().getMainPanel(), gridConstraints); + mainWindow.getMemoryPanel().add(MemoryForm.getInstance().getMainPanel(), gridConstraints); + mainWindow.getCpuPanel().add(CpuForm.getInstance().getMainPanel(), gridConstraints); + mainWindow.getNetworkPanel().add(NetworkForm.getInstance().getMainPanel(), gridConstraints); + mainWindow.getUsbPanel().add(UsbForm.getInstance().getMainPanel(), gridConstraints); + mainWindow.getVariablesPanel().add(VariablesForm.getInstance().getMainPanel(), gridConstraints); + mainWindow.getProcessesPanel().add(ProcessesForm.getInstance().getMainPanel(), gridConstraints); + mainWindow.getDiskPanel().add(DiskForm.getInstance().getMainPanel(), gridConstraints); + mainWindow.getPowerPanel().add(PowerSourceForm.getInstance().getMainPanel(), gridConstraints); + mainWindow.getMainPanel().updateUI(); + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + mainPanel = new JPanel(); + mainPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + tabbedPane = new JTabbedPane(); + tabbedPane.setTabLayoutPolicy(1); + mainPanel.add(tabbedPane, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, new Dimension(200, 200), null, 0, false)); + overviewPanel = new JPanel(); + overviewPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + tabbedPane.addTab("Overview", overviewPanel); + detailPanel = new JPanel(); + detailPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + tabbedPane.addTab("Detail", detailPanel); + memoryPanel = new JPanel(); + memoryPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + tabbedPane.addTab("Memory", memoryPanel); + cpuPanel = new JPanel(); + cpuPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + tabbedPane.addTab("CPU", cpuPanel); + diskPanel = new JPanel(); + diskPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + tabbedPane.addTab("Storage", diskPanel); + networkPanel = new JPanel(); + networkPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + tabbedPane.addTab("Network", networkPanel); + VariablesPanel = new JPanel(); + VariablesPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + tabbedPane.addTab("Variables", VariablesPanel); + processesPanel = new JPanel(); + processesPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + tabbedPane.addTab("Processes", processesPanel); + usbPanel = new JPanel(); + usbPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + tabbedPane.addTab("USB Devices", usbPanel); + powerPanel = new JPanel(); + powerPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + tabbedPane.addTab("Power", powerPanel); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return mainPanel; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/MemoryForm.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/MemoryForm.form new file mode 100644 index 0000000..452efc0 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/MemoryForm.form @@ -0,0 +1,245 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/MemoryForm.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/MemoryForm.java new file mode 100644 index 0000000..66a279a --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/MemoryForm.java @@ -0,0 +1,300 @@ +package io.fluent.pcinfo.ui.form; + +import cn.hutool.core.io.unit.DataSizeUtil; +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; + +import io.fluent.pcinfo.App; +import io.fluent.pcinfo.util.ScrollUtil; +import lombok.Getter; +import oshi.hardware.GlobalMemory; +import oshi.hardware.PhysicalMemory; +import oshi.hardware.VirtualMemory; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import java.awt.*; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * MemoryForm + * + * @author RememBerBer + * @since 2021/11/16. + */ +@Getter +public class MemoryForm { + private static final Log logger = LogFactory.get(); + + private static MemoryForm memoryForm; + private JPanel mainPanel; + private JProgressBar physicalMemoryProgressBar; + private JProgressBar virtualMemoryProgressBar; + private JLabel physicalMemoryTitle; + private JLabel physicalMemoryUsed; + private JLabel physicalMemoryAvailable; + private JLabel virtualMemoryTitle; + private JLabel virtualMemoryUsed; + private JLabel virtualMemoryAvailable; + private JLabel swapUsedLabel; + private JProgressBar swapProgressBar; + private JLabel swapAvailableLabel; + private JLabel swapTitle; + private JLabel jvmMemoryTitle; + private JProgressBar jvmProgressBar; + private JLabel jvmUsedLabel; + private JLabel jvmAvailableLabel; + private JLabel physicalMemoryInfoLabel; + private JScrollPane scrollPane; + private JTextPane physicalMemoryInfoTextPane; + + public static MemoryForm getInstance() { + if (memoryForm == null) { + memoryForm = new MemoryForm(); + } + return memoryForm; + } + + public static void init() { + memoryForm = getInstance(); + + initUi(); + initPhysicalMemoryInfo(); + + ScheduledExecutorService serviceStartPerSecond = Executors.newSingleThreadScheduledExecutor(); + serviceStartPerSecond.scheduleAtFixedRate(MemoryForm::initMemoryProgressInfo, 0, 1, TimeUnit.SECONDS); + + } + + private static void initPhysicalMemoryInfo() { + memoryForm.getPhysicalMemoryInfoTextPane().setText(getMemoryInfo()); + } + + private static void initUi() { + MemoryForm memoryForm = getInstance(); + JPanel mainPanel = memoryForm.getMainPanel(); + Font emphaticFont = new Font(mainPanel.getFont().getName(), Font.BOLD, mainPanel.getFont().getSize() + 2); + memoryForm.getPhysicalMemoryTitle().setFont(emphaticFont); + memoryForm.getVirtualMemoryTitle().setFont(emphaticFont); + memoryForm.getSwapTitle().setFont(emphaticFont); + memoryForm.getJvmMemoryTitle().setFont(emphaticFont); + memoryForm.getPhysicalMemoryInfoLabel().setFont(emphaticFont); + + Dimension d = new Dimension(-1, 100); + memoryForm.getPhysicalMemoryProgressBar().setMinimumSize(d); + + ScrollUtil.smoothPane(memoryForm.getScrollPane()); + + String contentType = "text/html; charset=utf-8"; + memoryForm.getPhysicalMemoryInfoTextPane().setContentType(contentType); + + } + + private static void initMemoryProgressInfo() { + GlobalMemory memory = App.si.getHardware().getMemory(); + + // global memory + long total = memory.getTotal(); + long available = memory.getAvailable(); + MemoryForm memoryForm = getInstance(); + JProgressBar physicalMemoryProgressBar = memoryForm.getPhysicalMemoryProgressBar(); + physicalMemoryProgressBar.setMaximum(100); + int usagePercent = (int) ((total - available) * 100 / total); + physicalMemoryProgressBar.setValue(usagePercent); + String progressStr = usagePercent + "%"; + physicalMemoryProgressBar.setToolTipText(progressStr); + physicalMemoryProgressBar.setStringPainted(true); + physicalMemoryProgressBar.setString(progressStr); + + memoryForm.getPhysicalMemoryUsed().setText("Used " + DataSizeUtil.format(total - available) + "/" + DataSizeUtil.format(total)); + memoryForm.getPhysicalMemoryAvailable().setText(DataSizeUtil.format(available) + "/" + DataSizeUtil.format(total) + " Available"); + + // virtual memory + VirtualMemory virtualMemory = memory.getVirtualMemory(); + long virtualMax = virtualMemory.getVirtualMax(); + long virtualInUse = virtualMemory.getVirtualInUse(); + JProgressBar virtualMemoryProgressBar = memoryForm.getVirtualMemoryProgressBar(); + virtualMemoryProgressBar.setMaximum(100); + int virtualUsagePercent = (int) (virtualInUse * 100 / virtualMax); + virtualMemoryProgressBar.setValue(virtualUsagePercent); + virtualMemoryProgressBar.setToolTipText(virtualUsagePercent + "%"); + memoryForm.getVirtualMemoryUsed().setText("Used " + DataSizeUtil.format(virtualInUse) + "/" + DataSizeUtil.format(virtualMax)); + memoryForm.getVirtualMemoryAvailable().setText(DataSizeUtil.format(virtualMax - virtualInUse) + "/" + DataSizeUtil.format(virtualMax) + " Available"); + + // swap memory + long swapTotal = virtualMemory.getSwapTotal(); + long swapUsed = virtualMemory.getSwapUsed(); + JProgressBar swapProgressBar = memoryForm.getSwapProgressBar(); + swapProgressBar.setMaximum(100); + + int swapUsagePercent = 0; + if (swapTotal != 0) { + swapUsagePercent = (int) (swapUsed * 100 / swapTotal); + + } + swapProgressBar.setValue(swapUsagePercent); + swapProgressBar.setToolTipText(swapUsagePercent + "%"); + memoryForm.getSwapUsedLabel().setText("Used " + DataSizeUtil.format(swapUsed) + "/" + DataSizeUtil.format(swapTotal) + " | page in " + virtualMemory.getSwapPagesIn() + " page out " + virtualMemory.getSwapPagesOut()); + memoryForm.getSwapAvailableLabel().setText(DataSizeUtil.format(swapTotal - swapUsed) + "/" + DataSizeUtil.format(swapTotal) + " Available"); + + long jvmTotal = Runtime.getRuntime().totalMemory(); + long jvmMax = Runtime.getRuntime().maxMemory(); + long jvmFree = Runtime.getRuntime().freeMemory(); + long jvmUsed = jvmTotal - jvmFree; + + JProgressBar jvmProgressBar = memoryForm.getJvmProgressBar(); + jvmProgressBar.setMaximum(100); + int jvmUsagePercent = (int) (jvmUsed * 100 / jvmTotal); + jvmProgressBar.setValue(jvmUsagePercent); + jvmProgressBar.setToolTipText(jvmUsagePercent + "%"); + memoryForm.getJvmUsedLabel().setText("Used " + DataSizeUtil.format(jvmUsed) + " / Total " + DataSizeUtil.format(jvmTotal) + " / Max " + DataSizeUtil.format(jvmMax)); + memoryForm.getJvmAvailableLabel().setText(""); + + } + + /** + * @return + */ + public static String getMemoryInfo() { + StringBuilder builder = new StringBuilder(); + GlobalMemory globalMemory = App.si.getHardware().getMemory(); + + builder.append("
"); + builder.append("Total: ").append(DataSizeUtil.format(globalMemory.getTotal())); + builder.append("
Page Size: ").append(DataSizeUtil.format(globalMemory.getPageSize())); + builder.append("
"); + + List physicalMemories = globalMemory.getPhysicalMemory(); + for (int i = 0; i < physicalMemories.size(); i++) { + PhysicalMemory physicalMemory = physicalMemories.get(i); + + builder.append("
Physical Memory: #").append(i); + builder.append("
BankLabel: ").append(physicalMemory.getBankLabel()); + builder.append("
Manufacturer: ").append(physicalMemory.getManufacturer()); + builder.append("
Capacity: ").append(DataSizeUtil.format(physicalMemory.getCapacity())); + builder.append("
Memory Type: ").append(physicalMemory.getMemoryType()); + builder.append("
Clock Speed: ").append(new BigDecimal(physicalMemory.getClockSpeed()).divide(new BigDecimal(1000000), 0, RoundingMode.HALF_UP)).append("MHz"); + + builder.append("
"); + } + + return builder.toString(); + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + mainPanel = new JPanel(); + mainPanel.setLayout(new GridLayoutManager(1, 1, new Insets(10, 10, 10, 10), -1, -1)); + scrollPane = new JScrollPane(); + mainPanel.add(scrollPane, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + scrollPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); + final JPanel panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(7, 1, new Insets(0, 0, 0, 0), -1, -1)); + scrollPane.setViewportView(panel1); + final JPanel panel2 = new JPanel(); + panel2.setLayout(new GridLayoutManager(3, 3, new Insets(10, 10, 10, 10), -1, -1)); + panel1.add(panel2, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + physicalMemoryTitle = new JLabel(); + physicalMemoryTitle.setText("Physical Memory"); + panel2.add(physicalMemoryTitle, new GridConstraints(0, 0, 1, 3, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + physicalMemoryProgressBar = new JProgressBar(); + panel2.add(physicalMemoryProgressBar, new GridConstraints(1, 0, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + physicalMemoryUsed = new JLabel(); + physicalMemoryUsed.setText("Used -"); + panel2.add(physicalMemoryUsed, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + physicalMemoryAvailable = new JLabel(); + physicalMemoryAvailable.setText("- Available"); + panel2.add(physicalMemoryAvailable, new GridConstraints(2, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + panel2.add(spacer1, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final JPanel panel3 = new JPanel(); + panel3.setLayout(new GridLayoutManager(3, 3, new Insets(10, 10, 10, 10), -1, -1)); + panel1.add(panel3, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + virtualMemoryTitle = new JLabel(); + virtualMemoryTitle.setText("Virtual Memory"); + panel3.add(virtualMemoryTitle, new GridConstraints(0, 0, 1, 3, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + virtualMemoryProgressBar = new JProgressBar(); + panel3.add(virtualMemoryProgressBar, new GridConstraints(1, 0, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + virtualMemoryUsed = new JLabel(); + virtualMemoryUsed.setText("Used -"); + panel3.add(virtualMemoryUsed, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + virtualMemoryAvailable = new JLabel(); + virtualMemoryAvailable.setText("- Available"); + panel3.add(virtualMemoryAvailable, new GridConstraints(2, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer2 = new Spacer(); + panel3.add(spacer2, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final JPanel panel4 = new JPanel(); + panel4.setLayout(new GridLayoutManager(3, 3, new Insets(10, 10, 10, 10), -1, -1)); + panel1.add(panel4, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + swapTitle = new JLabel(); + swapTitle.setText("Swap"); + panel4.add(swapTitle, new GridConstraints(0, 0, 1, 3, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + swapProgressBar = new JProgressBar(); + panel4.add(swapProgressBar, new GridConstraints(1, 0, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + swapUsedLabel = new JLabel(); + swapUsedLabel.setText("Used -"); + panel4.add(swapUsedLabel, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + swapAvailableLabel = new JLabel(); + swapAvailableLabel.setText("- Available"); + panel4.add(swapAvailableLabel, new GridConstraints(2, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer3 = new Spacer(); + panel4.add(spacer3, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final JPanel panel5 = new JPanel(); + panel5.setLayout(new GridLayoutManager(3, 3, new Insets(10, 10, 10, 10), -1, -1)); + panel1.add(panel5, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + jvmMemoryTitle = new JLabel(); + jvmMemoryTitle.setText("Java Runtime Memory of MooInfo"); + panel5.add(jvmMemoryTitle, new GridConstraints(0, 0, 1, 3, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + jvmProgressBar = new JProgressBar(); + panel5.add(jvmProgressBar, new GridConstraints(1, 0, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + jvmUsedLabel = new JLabel(); + jvmUsedLabel.setText("Used -"); + panel5.add(jvmUsedLabel, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + jvmAvailableLabel = new JLabel(); + jvmAvailableLabel.setText("- Available"); + panel5.add(jvmAvailableLabel, new GridConstraints(2, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer4 = new Spacer(); + panel5.add(spacer4, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final Spacer spacer5 = new Spacer(); + panel1.add(spacer5, new GridConstraints(6, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel6 = new JPanel(); + panel6.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel1.add(panel6, new GridConstraints(5, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + physicalMemoryInfoLabel = new JLabel(); + physicalMemoryInfoLabel.setText("Physical Memory Info"); + panel6.add(physicalMemoryInfoLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + physicalMemoryInfoTextPane = new JTextPane(); + panel6.add(physicalMemoryInfoTextPane, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JSeparator separator1 = new JSeparator(); + panel1.add(separator1, new GridConstraints(4, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return mainPanel; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/NetworkForm.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/NetworkForm.form new file mode 100644 index 0000000..84447cd --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/NetworkForm.form @@ -0,0 +1,105 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/NetworkForm.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/NetworkForm.java new file mode 100644 index 0000000..b1a9bc0 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/NetworkForm.java @@ -0,0 +1,332 @@ +package io.fluent.pcinfo.ui.form; + +import cn.hutool.core.io.unit.DataSizeUtil; +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; +import io.fluent.pcinfo.App; +import io.fluent.pcinfo.ui.Style; +import lombok.Getter; +import oshi.hardware.NetworkIF; +import oshi.software.os.NetworkParams; +import oshi.software.os.OperatingSystem; +import oshi.util.Constants; + +import javax.swing.*; +import javax.swing.table.*; +import java.awt.*; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.util.List; +import java.util.*; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * NetworkForm + * + * @author RememBerBer + * @since 2021/11/12. + */ +@Getter +public class NetworkForm { + private JPanel mainPanel; + private JTable interfacesTable; + private JPanel paramatersPanel; + private JTextPane parametersTextPane; + private JLabel uploadSpeedLabel; + private JLabel downloadSpeedLabel; + + private static final int INIT_HASH_SIZE = 100; + private static final String IP_ADDRESS_SEPARATOR = "; "; + private static final String[] COLUMNS = {"Name", "Index", "Speed", "IPv4 Address", "IPv6 address", "MAC address"}; + private static final double[] COLUMN_WIDTH_PERCENT = {0.02, 0.02, 0.1, 0.25, 0.45, 0.15}; + + private static final Log logger = LogFactory.get(); + + private static NetworkForm networkForm; + + private static Long downloadBefore; + private static Long uploadBefore; + private static Long timestampBefore; + + public static NetworkForm getInstance() { + if (networkForm == null) { + networkForm = new NetworkForm(); + } + return networkForm; + } + + public static void init() { + networkForm = getInstance(); + + initUi(); + initInfo(); + } + + private static void initUi() { + NetworkForm networkForm = getInstance(); + Style.emphaticIndicatorFont(networkForm.getUploadSpeedLabel()); + Style.emphaticIndicatorFont(networkForm.getDownloadSpeedLabel()); + } + + private static void initInfo() { + initParameters(); + initInterfaces(); + + ScheduledExecutorService serviceStartPerSecond = Executors.newSingleThreadScheduledExecutor(); + serviceStartPerSecond.scheduleAtFixedRate(NetworkForm::initNetworkSpeed, 0, 1, TimeUnit.SECONDS); + } + + /** + * Codes are copied from oshi and have some modifications. + */ + private static void initInterfaces() { + JTable interfacesTable = getInstance().getInterfacesTable(); + + List networkIfList = App.si.getHardware().getNetworkIFs(true); + + TableModel model = new DefaultTableModel(parseInterfaces(networkIfList), COLUMNS); + interfacesTable.setModel(model); + resizeColumns(interfacesTable.getColumnModel()); + + DefaultTableCellRenderer hr = (DefaultTableCellRenderer) interfacesTable.getTableHeader() + .getDefaultRenderer(); + // The name of header column turn to left + hr.setHorizontalAlignment(DefaultTableCellRenderer.LEFT); + interfacesTable.setShowGrid(true); + } + + private static void initParameters() { + JTextPane parametersTextPane = networkForm.getParametersTextPane(); + parametersTextPane.setContentType("text/plain; charset=utf-8"); + + String contentType = "text/html; charset=utf-8"; + parametersTextPane.setContentType(contentType); + parametersTextPane.setText(buildParamsText(App.si.getOperatingSystem())); + } + + private static void initNetworkSpeed() { + + String genericString; + try { + genericString = getDefaultNetworkInteface(); + } catch (Exception e) { + logger.error("NetworkSpeed not supported"); + return; + } + + long downloadNow = 0; + long uploadNow = 0; + long timestampNow = 0; + + List networkIFs = App.si.getHardware().getNetworkIFs(); + +// int i = 0; +// NetworkIF net = networkIFs.get(0); +// try { +// while (!networkIFs.get(i).getName().equals(genericString)) { +// net = networkIFs.get(i); +// i++; +// } +// } catch (ArrayIndexOutOfBoundsException e) { +// logger.error("NetworkSpeed not supported"); +// return; +// } +// net.updateAttributes(); + + for (int i = 0; i < networkIFs.size(); i++) { + NetworkIF net = networkIFs.get(i); + net.updateAttributes(); + downloadNow += net.getBytesRecv(); + uploadNow += net.getBytesSent(); + timestampNow = net.getTimeStamp(); + } + + if (downloadBefore == null) { + downloadBefore = downloadNow; + } + if (uploadBefore == null) { + uploadBefore = uploadNow; + } + if (timestampBefore == null) { + timestampBefore = timestampNow - 1; + } + + NetworkForm networkForm = getInstance(); + networkForm.getUploadSpeedLabel().setText("↓: " + DataSizeUtil.format((downloadNow - downloadBefore) / (timestampNow - timestampBefore) * 1000) + "/s"); + networkForm.getDownloadSpeedLabel().setText("↑: " + DataSizeUtil.format((uploadNow - uploadBefore) / (timestampNow - timestampBefore) * 1000) + "/s"); + + downloadBefore = downloadNow; + uploadBefore = uploadNow; + timestampBefore = timestampNow; + } + + private static String buildParamsText(OperatingSystem os) { + NetworkParams networkParams = os.getNetworkParams(); + StringBuilder builder = new StringBuilder(); + builder.append("
"); + builder.append("Domain Name: ").append(networkParams.getDomainName()); + builder.append("
Host Name: ").append(networkParams.getHostName()); + builder.append("
Ipv4 Default Gateway: ").append(networkParams.getIpv4DefaultGateway()); + builder.append("
Ipv6 Default Gateway: ").append(networkParams.getIpv6DefaultGateway()); + builder.append("
Dns Servers: ").append(Arrays.toString(networkParams.getDnsServers())); + builder.append("
"); + builder.append("
"); + return builder.toString(); + } + + /** + * Codes are copied from oshi and have some modifications. + * + * @param ipAddressArr + * @return + */ + private static String getIPAddressesString(String[] ipAddressArr) { + StringBuilder sb = new StringBuilder(); + boolean first = true; + + for (String ipAddress : ipAddressArr) { + if (first) { + first = false; + } else { + sb.append(IP_ADDRESS_SEPARATOR); + } + sb.append(ipAddress); + } + + return sb.toString(); + } + + /** + * Codes are copied from oshi and have some modifications. + * + * @param list + * @return + */ + private static Object[][] parseInterfaces(List list) { + Map intfSortValueMap = new HashMap<>(INIT_HASH_SIZE); + for (NetworkIF intf : list) { + intfSortValueMap.put(intf, intf.getIndex()); + } + List> intfList = new ArrayList<>(intfSortValueMap.entrySet()); + intfList.sort(Map.Entry.comparingByValue()); + + int i = 0; + Object[][] intfArr = new Object[intfList.size()][COLUMNS.length]; + + for (Map.Entry e : intfList) { + NetworkIF intf = e.getKey(); + + intfArr[i][0] = intf.getName(); + intfArr[i][1] = intf.getIndex(); + intfArr[i][2] = intf.getSpeed(); + intfArr[i][3] = getIPAddressesString(intf.getIPv4addr()); + intfArr[i][4] = getIPAddressesString(intf.getIPv6addr()); + intfArr[i][5] = Constants.UNKNOWN.equals(intf.getMacaddr()) ? "" : intf.getMacaddr(); + + i++; + } + + return intfArr; + } + + /** + * Codes are copied from oshi and have some modifications. + * + * @param tableColumnModel + */ + private static void resizeColumns(TableColumnModel tableColumnModel) { + TableColumn column; + int tW = tableColumnModel.getTotalColumnWidth(); + int cantCols = tableColumnModel.getColumnCount(); + for (int i = 0; i < cantCols; i++) { + column = tableColumnModel.getColumn(i); + int pWidth = (int) Math.round(COLUMN_WIDTH_PERCENT[i] * tW); + column.setPreferredWidth(pWidth); + } + } + + /** + * @return + * @throws Exception + */ + private static String getDefaultNetworkInteface() throws Exception { + Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); + + InetAddress localHost = InetAddress.getLocalHost(); + + while (networkInterfaces.hasMoreElements()) { + NetworkInterface networkInterface = networkInterfaces.nextElement(); + Enumeration inetAddresses = networkInterface.getInetAddresses(); + while (inetAddresses.hasMoreElements()) { + InetAddress inetAddress = inetAddresses.nextElement(); + if (inetAddress.equals(localHost)) { + return networkInterface.getName(); + } + } + } + return ""; + } + + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + mainPanel = new JPanel(); + mainPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + final JPanel panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(3, 1, new Insets(10, 20, 20, 20), -1, -1)); + mainPanel.add(panel1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + paramatersPanel = new JPanel(); + paramatersPanel.setLayout(new GridLayoutManager(1, 1, new Insets(10, 0, 10, 0), -1, -1)); + panel1.add(paramatersPanel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + parametersTextPane = new JTextPane(); + parametersTextPane.setEditable(true); + paramatersPanel.add(parametersTextPane, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JScrollPane scrollPane1 = new JScrollPane(); + panel1.add(scrollPane1, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + interfacesTable = new JTable(); + scrollPane1.setViewportView(interfacesTable); + final JPanel panel2 = new JPanel(); + panel2.setLayout(new GridLayoutManager(1, 3, new Insets(20, 10, 10, 10), -1, -1)); + panel1.add(panel2, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + panel2.add(spacer1, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final JPanel panel3 = new JPanel(); + panel3.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + panel2.add(panel3, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + uploadSpeedLabel = new JLabel(); + uploadSpeedLabel.setText(" ↑: --"); + panel3.add(uploadSpeedLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel4 = new JPanel(); + panel4.setLayout(new GridLayoutManager(1, 1, new Insets(0, 10, 0, 0), -1, -1)); + panel2.add(panel4, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + downloadSpeedLabel = new JLabel(); + downloadSpeedLabel.setText(" ↓: --"); + panel4.add(downloadSpeedLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return mainPanel; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/OverviewForm.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/OverviewForm.form new file mode 100644 index 0000000..580afac --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/OverviewForm.form @@ -0,0 +1,356 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/OverviewForm.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/OverviewForm.java new file mode 100644 index 0000000..ff4cfe0 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/OverviewForm.java @@ -0,0 +1,467 @@ +package io.fluent.pcinfo.ui.form; + +import cn.hutool.core.io.unit.DataSizeUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.formdev.flatlaf.extras.FlatSVGIcon; +import com.google.common.collect.Maps; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; +import io.fluent.pcinfo.App; +import io.fluent.pcinfo.ui.Style; +import io.fluent.pcinfo.util.ScrollUtil; +import lombok.Getter; +import oshi.hardware.*; +import oshi.software.os.OperatingSystem; +import oshi.util.EdidUtil; +import oshi.util.FormatUtil; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import java.awt.*; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * OverviewForm + * + * @author RememBerBer + * @since 2021/11/12. + */ +@Getter +public class OverviewForm { + private static final Log logger = LogFactory.get(); + + private static OverviewForm overviewForm; + private JPanel mainPanel; + private JLabel deviceNameLabel; + private JLabel osNameLabel; + private JLabel cpuLabel; + private JLabel cpuInfo; + private JLabel memoryLabel; + private JLabel memoryInfo; + private JLabel graphicsCardLabel; + private JLabel graphicsCardInfo; + private JLabel baseBoardLabel; + private JLabel baseBoardInfoLabel; + private JLabel diskStorageLabel; + private JLabel diskStorageInfoLabel; + private JLabel displayInfoLabel; + private JLabel displayLabel; + private JLabel soundCardLabel; + private JLabel soundCardInfoLabel; + private JLabel powerSourceLabel; + private JLabel powerSourceInfoLabel; + private JLabel firmwareInfoLabel; + private JLabel firmwareLabel; + private JScrollPane scrollPane; + + public static OverviewForm getInstance() { + if (overviewForm == null) { + overviewForm = new OverviewForm(); + } + return overviewForm; + } + + public static void init() { + overviewForm = getInstance(); + + initUi(); + initInfo(); + } + + private static void initUi() { + OverviewForm overviewForm = getInstance(); + + Style.emphaticIndicatorFont(overviewForm.getDeviceNameLabel()); + Style.emphaticIndicatorFont(overviewForm.getOsNameLabel()); + + Style.emphaticLabelFont(overviewForm.getCpuLabel()); + Style.emphaticLabelFont(overviewForm.getMemoryLabel()); + Style.emphaticLabelFont(overviewForm.getGraphicsCardLabel()); + Style.emphaticLabelFont(overviewForm.getBaseBoardLabel()); + Style.emphaticLabelFont(overviewForm.getDiskStorageLabel()); + Style.emphaticLabelFont(overviewForm.getDisplayLabel()); + Style.emphaticLabelFont(overviewForm.getSoundCardLabel()); + Style.emphaticLabelFont(overviewForm.getPowerSourceLabel()); + Style.emphaticLabelFont(overviewForm.getFirmwareLabel()); + + overviewForm.getCpuLabel().setIcon(new FlatSVGIcon("icons/cpu.svg", 20, 20)); + overviewForm.getMemoryLabel().setIcon(new FlatSVGIcon("icons/memory.svg", 20, 20)); + overviewForm.getGraphicsCardLabel().setIcon(new FlatSVGIcon("icons/graphicsCard.svg", 20, 20)); + overviewForm.getBaseBoardLabel().setIcon(new FlatSVGIcon("icons/chip.svg", 20, 20)); + overviewForm.getDiskStorageLabel().setIcon(new FlatSVGIcon("icons/storage.svg", 20, 20)); + overviewForm.getDisplayLabel().setIcon(new FlatSVGIcon("icons/display.svg", 20, 20)); + overviewForm.getSoundCardLabel().setIcon(new FlatSVGIcon("icons/sound.svg", 20, 20)); + overviewForm.getPowerSourceLabel().setIcon(new FlatSVGIcon("icons/battery.svg", 20, 20)); + overviewForm.getFirmwareLabel().setIcon(new FlatSVGIcon("icons/firmware.svg", 20, 20)); + + ScrollUtil.smoothPane(overviewForm.getScrollPane()); + } + + private static void initInfo() { + OverviewForm overviewForm = getInstance(); + + HardwareAbstractionLayer hardware = App.si.getHardware(); + + ComputerSystem computerSystem = hardware.getComputerSystem(); + StringBuilder deviceNameBuilder = new StringBuilder(); + deviceNameBuilder.append(computerSystem.getManufacturer()); + if (!"unknown".equalsIgnoreCase(computerSystem.getModel())) { + deviceNameBuilder.append(" ").append(computerSystem.getModel()); + } + overviewForm.getDeviceNameLabel().setText(deviceNameBuilder.toString()); + + OperatingSystem operatingSystem = App.si.getOperatingSystem(); + overviewForm.getOsNameLabel().setText(operatingSystem.toString()); + + overviewForm.getCpuInfo().setText(hardware.getProcessor().getProcessorIdentifier().getName()); + overviewForm.getMemoryInfo().setText(getMemoryInfo(hardware.getMemory())); + overviewForm.getGraphicsCardInfo().setText(getGraphicsCardInfo(hardware)); + overviewForm.getBaseBoardInfoLabel().setText(getBaseBoardInfo(hardware.getComputerSystem().getBaseboard())); + overviewForm.getDiskStorageInfoLabel().setText(getDiskStorageInfo(hardware)); + overviewForm.getDisplayInfoLabel().setText(getDisplayInfo(hardware)); + overviewForm.getSoundCardInfoLabel().setText(getSoundCardInfo(hardware)); + overviewForm.getPowerSourceInfoLabel().setText(getPowerSourceInfo(hardware)); + overviewForm.getFirmwareInfoLabel().setText(getFirmware(hardware)); + + } + + /** + * memory info text,like:"16 GB (SamSung DDR4 3200MHZ 8GB + SamSung DDR4 3200MHZ 8GB)" + * + * @param memory + * @return + */ + private static String getMemoryInfo(GlobalMemory memory) { + StringBuilder memoryInfoBuilder = new StringBuilder(); + + long totalCapacity = 0; + List detailList = new ArrayList<>(); + + List physicalMemories = memory.getPhysicalMemory(); + StringBuilder detailBuilder; + for (PhysicalMemory physicalMemory : physicalMemories) { + detailBuilder = new StringBuilder(); + totalCapacity += physicalMemory.getCapacity(); + detailBuilder.append(physicalMemory.getManufacturer()); + detailBuilder.append(" ").append(physicalMemory.getMemoryType()); + detailBuilder.append(" ").append(new BigDecimal(physicalMemory.getClockSpeed()).divide(new BigDecimal(1000000), 0, RoundingMode.HALF_UP)).append("MHz"); + detailBuilder.append(" ").append(DataSizeUtil.format(physicalMemory.getCapacity())); + detailList.add(detailBuilder.toString()); + } + memoryInfoBuilder.append(DataSizeUtil.format(totalCapacity)); + memoryInfoBuilder.append(" (").append(StrUtil.join(" + ", detailList)).append(")"); + + return memoryInfoBuilder.toString(); + } + + /** + * GraphicsCard info text,like:"NVIDIA GeForce MX450 8 GB + Intel(R) Iris(R) Xe Graphics 8 GB" + * + * @param hardware + * @return + */ + private static String getGraphicsCardInfo(HardwareAbstractionLayer hardware) { + List detailList = new ArrayList<>(); + StringBuilder detailBuilder; + List graphicsCards = hardware.getGraphicsCards(); + for (GraphicsCard graphicsCard : graphicsCards) { + detailBuilder = new StringBuilder(); + detailBuilder.append(graphicsCard.getName()); + detailBuilder.append(" ").append(DataSizeUtil.format(graphicsCard.getVRam())); + + detailList.add(detailBuilder.toString()); + } + return StrUtil.join(" + ", detailList); + } + + /** + * @return + */ + private static String getBaseBoardInfo(Baseboard baseboard) { + StringBuilder detailBuilder = new StringBuilder(); + detailBuilder.append(baseboard.getManufacturer()); + if (!"unknown".equals(baseboard.getModel())) { + detailBuilder.append(" ").append(baseboard.getModel()); + } + if (!"unknown".equals(baseboard.getVersion())) { + detailBuilder.append(" ").append(baseboard.getVersion()); + } + return detailBuilder.toString(); + } + + /** + * Disk Storage info text,like:"KBG40ZNV512G KIOXIA (标准磁盘驱动器) 512 GB" + * + * @param hardware + * @return + */ + private static String getDiskStorageInfo(HardwareAbstractionLayer hardware) { + List detailList = new ArrayList<>(); + StringBuilder detailBuilder; + List diskStores = hardware.getDiskStores(); + for (HWDiskStore hwDiskStore : diskStores) { + detailBuilder = new StringBuilder(); + detailBuilder.append(hwDiskStore.getModel()); + detailBuilder.append(" ").append(hwDiskStore.getSize() > 0 ? FormatUtil.formatBytesDecimal(hwDiskStore.getSize()) : "?"); + + detailList.add(detailBuilder.toString()); + } + return StrUtil.join(" + ", detailList); + } + + /** + * Display Info + * + * @param hardware + * @return + */ + private static String getDisplayInfo(HardwareAbstractionLayer hardware) { + List detailList = new ArrayList<>(); + StringBuilder detailBuilder; + + List displays = hardware.getDisplays(); + for (Display display : displays) { + detailBuilder = new StringBuilder(); + byte[] edid = display.getEdid(); + byte[][] desc = EdidUtil.getDescriptors(edid); + Map infoMap = Maps.newHashMap(); + for (byte[] b : desc) { + int descriptorType = EdidUtil.getDescriptorType(b); + if (descriptorType == 0xff || descriptorType == 0xfe || descriptorType == 0xfd || descriptorType == 0xfb || descriptorType == 0xfa) { + } else if (descriptorType == 0xfc) { + infoMap.put("name", EdidUtil.getDescriptorText(b)); + } else { + if (EdidUtil.getDescriptorType(b) > 0x0f || EdidUtil.getDescriptorType(b) < 0x00) { + infoMap.put("size", EdidUtil.getTimingDescriptor(b)); + } + } + } + + detailBuilder.append(infoMap.get("name")); + detailBuilder.append(" ").append(infoMap.get("size")); + + detailList.add(detailBuilder.toString()); + + } + + return StrUtil.join(" + ", detailList); + } + + /** + * @param hardware + * @return + */ + private static String getSoundCardInfo(HardwareAbstractionLayer hardware) { + List detailList = new ArrayList<>(); + StringBuilder detailBuilder; + List soundCards = hardware.getSoundCards(); + for (SoundCard soundCard : soundCards) { + detailBuilder = new StringBuilder(); + detailBuilder.append(soundCard.getName()); + + detailList.add(detailBuilder.toString()); + } + + return StrUtil.join(" + ", detailList); + + } + + /** + * PowerSourceInfo + * + * @param hardware + * @return + */ + private static String getPowerSourceInfo(HardwareAbstractionLayer hardware) { + List detailList = new ArrayList<>(); + StringBuilder detailBuilder; + List powerSources = hardware.getPowerSources(); + for (PowerSource powerSource : powerSources) { + detailBuilder = new StringBuilder(); + detailBuilder.append(powerSource.getName()); + detailBuilder.append(" ").append(powerSource.getManufacturer()); + detailBuilder.append(" ").append(powerSource.getDeviceName()); + if (!"unknown".equals(powerSource.getChemistry())) { + detailBuilder.append(" ").append(powerSource.getChemistry()); + } + detailBuilder.append(" ").append(powerSource.getMaxCapacity()).append("/").append(powerSource.getDesignCapacity()); + detailBuilder.append("(").append(powerSource.getCapacityUnits()).append(")"); + + detailList.add(detailBuilder.toString()); + } + + return StrUtil.join(" + ", detailList); + + } + + /** + * Firmware + * + * @param hardware + * @return + */ + private static String getFirmware(HardwareAbstractionLayer hardware) { + Firmware firmware = hardware.getComputerSystem().getFirmware(); + + StringBuilder detailBuilder = new StringBuilder(); + detailBuilder.append(firmware.getManufacturer()); + detailBuilder.append(" ").append(firmware.getName()); + detailBuilder.append(" ").append(firmware.getDescription()); + detailBuilder.append(" ").append(firmware.getVersion()); + detailBuilder.append(" ").append(firmware.getReleaseDate()); + + return detailBuilder.toString(); + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + mainPanel = new JPanel(); + mainPanel.setLayout(new GridLayoutManager(1, 1, new Insets(10, 10, 10, 10), -1, -1)); + scrollPane = new JScrollPane(); + mainPanel.add(scrollPane, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + scrollPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); + final JPanel panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(4, 1, new Insets(0, 0, 0, 0), -1, -1)); + scrollPane.setViewportView(panel1); + final JPanel panel2 = new JPanel(); + panel2.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel1.add(panel2, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JPanel panel3 = new JPanel(); + panel3.setLayout(new GridLayoutManager(1, 2, new Insets(10, 10, 10, 10), -1, -1)); + panel2.add(panel3, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + deviceNameLabel = new JLabel(); + deviceNameLabel.setText("Device Name"); + panel3.add(deviceNameLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + panel3.add(spacer1, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final JPanel panel4 = new JPanel(); + panel4.setLayout(new GridLayoutManager(1, 2, new Insets(10, 10, 10, 10), -1, -1)); + panel2.add(panel4, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + osNameLabel = new JLabel(); + osNameLabel.setText("OS Name"); + panel4.add(osNameLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer2 = new Spacer(); + panel4.add(spacer2, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final Spacer spacer3 = new Spacer(); + panel1.add(spacer3, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JPanel panel5 = new JPanel(); + panel5.setLayout(new GridLayoutManager(9, 3, new Insets(10, 20, 10, 10), -1, -1)); + panel1.add(panel5, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + cpuInfo = new JLabel(); + cpuInfo.setText("CPU info"); + panel5.add(cpuInfo, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + memoryInfo = new JLabel(); + memoryInfo.setText("Memory info"); + panel5.add(memoryInfo, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + graphicsCardInfo = new JLabel(); + graphicsCardInfo.setText("GraphicsCard info"); + panel5.add(graphicsCardInfo, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + baseBoardInfoLabel = new JLabel(); + baseBoardInfoLabel.setText("BaseBoard info"); + panel5.add(baseBoardInfoLabel, new GridConstraints(3, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + diskStorageInfoLabel = new JLabel(); + diskStorageInfoLabel.setText("DiskStorage info"); + panel5.add(diskStorageInfoLabel, new GridConstraints(4, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + displayInfoLabel = new JLabel(); + displayInfoLabel.setText("Display info"); + panel5.add(displayInfoLabel, new GridConstraints(5, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + soundCardInfoLabel = new JLabel(); + soundCardInfoLabel.setText("SoundCard info"); + panel5.add(soundCardInfoLabel, new GridConstraints(6, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + powerSourceInfoLabel = new JLabel(); + powerSourceInfoLabel.setText("PowerSource info"); + panel5.add(powerSourceInfoLabel, new GridConstraints(7, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + firmwareInfoLabel = new JLabel(); + firmwareInfoLabel.setText("Firmware info"); + panel5.add(firmwareInfoLabel, new GridConstraints(8, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer4 = new Spacer(); + panel5.add(spacer4, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final JPanel panel6 = new JPanel(); + panel6.setLayout(new GridLayoutManager(1, 1, new Insets(5, 0, 5, 0), -1, -1)); + panel5.add(panel6, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + cpuLabel = new JLabel(); + cpuLabel.setText("CPU"); + panel6.add(cpuLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel7 = new JPanel(); + panel7.setLayout(new GridLayoutManager(1, 1, new Insets(5, 0, 5, 0), -1, -1)); + panel5.add(panel7, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + memoryLabel = new JLabel(); + memoryLabel.setText("Memory"); + panel7.add(memoryLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel8 = new JPanel(); + panel8.setLayout(new GridLayoutManager(1, 1, new Insets(5, 0, 5, 0), -1, -1)); + panel5.add(panel8, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + graphicsCardLabel = new JLabel(); + graphicsCardLabel.setText("GraphicsCard"); + panel8.add(graphicsCardLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel9 = new JPanel(); + panel9.setLayout(new GridLayoutManager(1, 1, new Insets(5, 0, 5, 0), -1, -1)); + panel5.add(panel9, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + baseBoardLabel = new JLabel(); + baseBoardLabel.setText("BaseBoard"); + panel9.add(baseBoardLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel10 = new JPanel(); + panel10.setLayout(new GridLayoutManager(1, 1, new Insets(5, 0, 5, 0), -1, -1)); + panel5.add(panel10, new GridConstraints(4, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + diskStorageLabel = new JLabel(); + diskStorageLabel.setText("DiskStorage"); + panel10.add(diskStorageLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel11 = new JPanel(); + panel11.setLayout(new GridLayoutManager(1, 1, new Insets(5, 0, 5, 0), -1, -1)); + panel5.add(panel11, new GridConstraints(5, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + displayLabel = new JLabel(); + displayLabel.setText("Display"); + panel11.add(displayLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel12 = new JPanel(); + panel12.setLayout(new GridLayoutManager(1, 1, new Insets(5, 0, 5, 0), -1, -1)); + panel5.add(panel12, new GridConstraints(6, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + soundCardLabel = new JLabel(); + soundCardLabel.setText("SoundCard"); + panel12.add(soundCardLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel13 = new JPanel(); + panel13.setLayout(new GridLayoutManager(1, 1, new Insets(5, 0, 5, 0), -1, -1)); + panel5.add(panel13, new GridConstraints(7, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + powerSourceLabel = new JLabel(); + powerSourceLabel.setText("PowerSource"); + panel13.add(powerSourceLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel14 = new JPanel(); + panel14.setLayout(new GridLayoutManager(1, 1, new Insets(5, 0, 5, 0), -1, -1)); + panel5.add(panel14, new GridConstraints(8, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + firmwareLabel = new JLabel(); + firmwareLabel.setText("Firmware"); + panel14.add(firmwareLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JPanel panel15 = new JPanel(); + panel15.setLayout(new GridLayoutManager(1, 1, new Insets(0, 10, 0, 10), -1, -1)); + panel1.add(panel15, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JSeparator separator1 = new JSeparator(); + panel15.add(separator1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return mainPanel; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/PowerSourceForm.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/PowerSourceForm.form new file mode 100644 index 0000000..a8a9998 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/PowerSourceForm.form @@ -0,0 +1,57 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/PowerSourceForm.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/PowerSourceForm.java new file mode 100644 index 0000000..dc5017b --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/PowerSourceForm.java @@ -0,0 +1,237 @@ +package io.fluent.pcinfo.ui.form; + +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.formdev.flatlaf.extras.FlatSVGIcon; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; + +import io.fluent.pcinfo.App; +import io.fluent.pcinfo.ui.Style; +import io.fluent.pcinfo.util.ScrollUtil; +import lombok.Getter; +import oshi.hardware.PowerSource; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import java.awt.*; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * NetworkForm + * + * @author RememBerBer + * @since 2021/11/21. + */ +@Getter +public class PowerSourceForm { + private JPanel mainPanel; + private JPanel powerBasePanel; + private JPanel powerInfoPanel; + private JTextPane powerInfoTextPane; + private JScrollPane scrollPane; + + private static final Log logger = LogFactory.get(); + + private static PowerSourceForm powerSourceForm; + + public static PowerSourceForm getInstance() { + if (powerSourceForm == null) { + powerSourceForm = new PowerSourceForm(); + } + return powerSourceForm; + } + + public static void init() { + powerSourceForm = getInstance(); + + initUi(); + ScheduledExecutorService serviceStartPerSecond = Executors.newSingleThreadScheduledExecutor(); + serviceStartPerSecond.scheduleAtFixedRate(PowerSourceForm::initInfo, 0, 10, TimeUnit.SECONDS); + } + + private static void initUi() { + ScrollUtil.smoothPane(getInstance().getScrollPane()); + } + + private static void initInfo() { + List powerSources = App.si.getHardware().getPowerSources(); + PowerSourceForm powerSourceForm = getInstance(); + JPanel powerBasePanel = powerSourceForm.getPowerBasePanel(); + + powerBasePanel.removeAll(); + + powerBasePanel.setLayout(new GridLayoutManager(powerSources.size(), 1, new Insets(0, 0, 0, 0), -1, -1)); + + for (int i = 0; i < powerSources.size(); i++) { + + PowerSource powerSource = powerSources.get(i); + + JPanel powerPanel = new JPanel(); + powerPanel.setLayout(new GridLayoutManager(3, 4, new Insets(10, 10, 10, 10), -1, -1)); + + JLabel powerNameLabel = new JLabel(); + Style.emphaticTitleFont(powerNameLabel); + StringBuilder powerNameBuilder = new StringBuilder(); + powerNameBuilder.append(powerSource.getName()); + powerNameBuilder.append(" ").append(powerSource.getManufacturer()); + powerNameBuilder.append(" ").append(powerSource.getDeviceName()); + if (!"unknown".equals(powerSource.getChemistry())) { + powerNameBuilder.append(" ").append(powerSource.getChemistry()); + } + powerNameLabel.setText(powerNameBuilder.toString()); + powerPanel.add(powerNameLabel, new GridConstraints(0, 0, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + + JProgressBar progressBar1 = new JProgressBar(); + progressBar1.setMaximum(100); + double remainingCapacityPercent = powerSource.getRemainingCapacityPercent(); + int remainingCapacityPercentInt = (int) (remainingCapacityPercent * 100); + progressBar1.setValue(remainingCapacityPercentInt); + progressBar1.setStringPainted(true); + progressBar1.setString(remainingCapacityPercentInt + "%"); + Dimension d = new Dimension(-1, 100); + progressBar1.setMinimumSize(d); + powerPanel.add(progressBar1, new GridConstraints(1, 0, 1, 4, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + + JLabel capacityLabel = new JLabel(); + + StringBuilder capacityBuilder = new StringBuilder(); + capacityBuilder.append("Current ").append(powerSource.getCurrentCapacity()); + capacityBuilder.append(" / ").append("Max ").append(powerSource.getMaxCapacity()); + capacityBuilder.append(" / ").append("Design ").append(powerSource.getDesignCapacity()); + capacityBuilder.append(" (").append(powerSource.getCapacityUnits()).append(") "); + capacityBuilder.append((powerSource.getDesignCapacity() - powerSource.getMaxCapacity()) * 100 / powerSource.getDesignCapacity()).append("% wastage"); + capacityLabel.setText(capacityBuilder.toString()); + powerPanel.add(capacityLabel, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + + JLabel temperatureLabel = new JLabel(); + temperatureLabel.setHorizontalAlignment(SwingConstants.RIGHT); + temperatureLabel.setHorizontalTextPosition(SwingConstants.RIGHT); + + StringBuilder powerTextBuilder = new StringBuilder(); + if (powerSource.isCharging()) { + temperatureLabel.setIcon(new FlatSVGIcon("icons/Charging.svg")); + powerTextBuilder.append("Charging"); + } else { + temperatureLabel.setIcon(new FlatSVGIcon("icons/indicator_light.svg", 10, 10)); + powerTextBuilder.append("Remaining Time: " + formatTimeRemaining(powerSource.getTimeRemainingEstimated())); + } + + powerTextBuilder.append(String.format(" / %.1f°C", powerSource.getTemperature())); + temperatureLabel.setText(powerTextBuilder.toString()); + powerPanel.add(temperatureLabel, new GridConstraints(2, 3, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + + final Spacer spacer2 = new Spacer(); + powerPanel.add(spacer2, new GridConstraints(2, 1, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + + JLabel label1 = new JLabel(); + powerPanel.add(label1, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer3 = new Spacer(); + powerPanel.add(spacer3, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + + powerBasePanel.add(powerPanel, new GridConstraints(i, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + } + + // info textPane + powerSourceForm.getPowerInfoTextPane().setContentType("text/html; charset=utf-8"); + powerSourceForm.getPowerInfoTextPane().setText(getPowerInfoText(powerSources)); + + } + + public static String getPowerInfoText(List powerSources) { + StringBuilder powerInfoBuilder = new StringBuilder(); + + for (PowerSource powerSource : powerSources) { + powerInfoBuilder.append("
"); + powerInfoBuilder.append("Name: ").append(powerSource.getName()); + powerInfoBuilder.append("
Device Name: ").append(powerSource.getDeviceName()); + powerInfoBuilder.append("
Remaining Capacity Percent: ").append(powerSource.getRemainingCapacityPercent() * 100).append("%"); + powerInfoBuilder.append("
Time Remaining: ").append(formatTimeRemaining(powerSource.getTimeRemainingEstimated())); + powerInfoBuilder.append("
Time Remaining Instant: ").append(formatTimeRemaining(powerSource.getTimeRemainingInstant())); + powerInfoBuilder.append("
Power Usage Rate: ").append(powerSource.getPowerUsageRate()); + powerInfoBuilder.append("
Voltage: ").append(powerSource.getVoltage()); + powerInfoBuilder.append("
Amperage: ").append(powerSource.getAmperage()); + powerInfoBuilder.append("
Temperature: ").append(String.format("%.1f°C", powerSource.getTemperature())); + powerInfoBuilder.append("
Power OnLine: ").append(powerSource.isPowerOnLine()); + powerInfoBuilder.append("
Charging: ").append(powerSource.isCharging()); + powerInfoBuilder.append("
Discharging: ").append(powerSource.isDischarging()); + powerInfoBuilder.append("
Cycle Count: ").append(powerSource.getCycleCount()); + powerInfoBuilder.append("
Chemistry: ").append(powerSource.getChemistry()); + powerInfoBuilder.append("
Manufacturer: ").append(powerSource.getManufacturer()); + powerInfoBuilder.append("
Manufacture Date: ").append(powerSource.getManufactureDate()); + powerInfoBuilder.append("
Serial Number: ").append(powerSource.getSerialNumber()); + + powerInfoBuilder.append("
>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + mainPanel = new JPanel(); + mainPanel.setLayout(new GridLayoutManager(1, 1, new Insets(10, 10, 10, 10), -1, -1)); + scrollPane = new JScrollPane(); + mainPanel.add(scrollPane, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + scrollPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); + final JPanel panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1)); + scrollPane.setViewportView(panel1); + powerBasePanel = new JPanel(); + powerBasePanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + panel1.add(powerBasePanel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + powerInfoPanel = new JPanel(); + powerInfoPanel.setLayout(new GridLayoutManager(1, 1, new Insets(10, 10, 10, 10), -1, -1)); + panel1.add(powerInfoPanel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + powerInfoTextPane = new JTextPane(); + powerInfoTextPane.setEditable(true); + powerInfoPanel.add(powerInfoTextPane, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return mainPanel; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/PowerSourceLayoutDesignForm.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/PowerSourceLayoutDesignForm.form new file mode 100644 index 0000000..9565e5f --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/PowerSourceLayoutDesignForm.form @@ -0,0 +1,170 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/PowerSourceLayoutDesignForm.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/PowerSourceLayoutDesignForm.java new file mode 100644 index 0000000..4c6af79 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/PowerSourceLayoutDesignForm.java @@ -0,0 +1,137 @@ +package io.fluent.pcinfo.ui.form; + +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; +import lombok.Getter; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import java.awt.*; + +/** + * NetworkForm + * + * @author RememBerBer + * @since 2021/11/21. + */ +@Getter +public class PowerSourceLayoutDesignForm { + private JPanel mainPanel; + private JProgressBar progressBar1; + private JLabel powerNameLabel; + private JPanel powerPanel; + private JLabel capacityLabel; + private JLabel temperatureLabel; + private JLabel powerCapacityLabel; + private JLabel temperatureLabel1; + private JLabel powerNameLabel1; + private JPanel panel1; + private JProgressBar progressBar2; + private JPanel powerBasePanel; + private JPanel powerInfoPanel; + private JTextPane powerInfoTextPane; + + private static final Log logger = LogFactory.get(); + + private static PowerSourceLayoutDesignForm powerSourceForm; + + public static PowerSourceLayoutDesignForm getInstance() { + if (powerSourceForm == null) { + powerSourceForm = new PowerSourceLayoutDesignForm(); + } + return powerSourceForm; + } + + public static void init() { + powerSourceForm = getInstance(); + +// initUi(); +// initInfo(); + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + mainPanel = new JPanel(); + mainPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + final JScrollPane scrollPane1 = new JScrollPane(); + mainPanel.add(scrollPane1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + scrollPane1.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); + final JPanel panel2 = new JPanel(); + panel2.setLayout(new GridLayoutManager(3, 1, new Insets(10, 10, 10, 10), -1, -1)); + scrollPane1.setViewportView(panel2); + final Spacer spacer1 = new Spacer(); + panel2.add(spacer1, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + powerBasePanel = new JPanel(); + powerBasePanel.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1)); + panel2.add(powerBasePanel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + powerPanel = new JPanel(); + powerPanel.setLayout(new GridLayoutManager(3, 4, new Insets(10, 10, 10, 10), -1, -1)); + powerBasePanel.add(powerPanel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + powerNameLabel = new JLabel(); + powerNameLabel.setText("PowerName"); + powerPanel.add(powerNameLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + progressBar1 = new JProgressBar(); + powerPanel.add(progressBar1, new GridConstraints(1, 0, 1, 4, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + capacityLabel = new JLabel(); + capacityLabel.setText("PowerCapacity"); + powerPanel.add(capacityLabel, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer2 = new Spacer(); + powerPanel.add(spacer2, new GridConstraints(2, 1, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final JLabel label1 = new JLabel(); + label1.setHorizontalAlignment(11); + label1.setHorizontalTextPosition(11); + label1.setText("Label"); + powerPanel.add(label1, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer3 = new Spacer(); + powerPanel.add(spacer3, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + temperatureLabel = new JLabel(); + temperatureLabel.setText("Temperature"); + powerPanel.add(temperatureLabel, new GridConstraints(2, 3, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(3, 3, new Insets(10, 10, 10, 10), -1, -1)); + powerBasePanel.add(panel1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + powerNameLabel1 = new JLabel(); + powerNameLabel1.setText("PowerName"); + panel1.add(powerNameLabel1, new GridConstraints(0, 0, 1, 3, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + progressBar2 = new JProgressBar(); + panel1.add(progressBar2, new GridConstraints(1, 0, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + powerCapacityLabel = new JLabel(); + powerCapacityLabel.setText("PowerCapacity"); + panel1.add(powerCapacityLabel, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + temperatureLabel1 = new JLabel(); + temperatureLabel1.setText("Temperature"); + panel1.add(temperatureLabel1, new GridConstraints(2, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer4 = new Spacer(); + panel1.add(spacer4, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + powerInfoPanel = new JPanel(); + powerInfoPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + panel2.add(powerInfoPanel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + powerInfoTextPane = new JTextPane(); + powerInfoTextPane.setEditable(false); + powerInfoPanel.add(powerInfoTextPane, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW, null, new Dimension(150, 50), null, 0, false)); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return mainPanel; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/ProcessesForm.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/ProcessesForm.form new file mode 100644 index 0000000..83c49e7 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/ProcessesForm.form @@ -0,0 +1,97 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/ProcessesForm.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/ProcessesForm.java new file mode 100644 index 0000000..dd820d0 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/ProcessesForm.java @@ -0,0 +1,406 @@ +package io.fluent.pcinfo.ui.form; + +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; + +import io.fluent.pcinfo.App; +import io.fluent.pcinfo.ui.UiConsts; +import io.fluent.pcinfo.util.SystemUtil; +import lombok.Getter; +import org.apache.commons.imaging.formats.icns.IcnsImageParser; +import oshi.PlatformEnum; +import oshi.SystemInfo; +import oshi.software.os.OSProcess; +import oshi.software.os.OperatingSystem; +import oshi.util.FormatUtil; +import xmlwise.Plist; + +import javax.swing.Timer; +import javax.swing.*; +import javax.swing.filechooser.FileSystemView; +import javax.swing.table.*; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; +import java.util.*; + +/** + * ProcessesForm + * + * @author RememBerBer + * @since 2021/11/15. + */ +@Getter +public class ProcessesForm { + private static final String[] COLUMNS = {"Icon", "PID", "PPID", "Threads", "% CPU", "Cumulative", "VSZ", "RSS", "% Memory", + "Process Name"}; + private static final double[] COLUMN_WIDTH_PERCENT = {0.01, 0.07, 0.07, 0.07, 0.07, 0.09, 0.1, 0.1, 0.08, 0.35}; + + private final static Map priorSnapshotMap = new HashMap<>(); + private final static HashMap iconCacheMap = new HashMap<>(); + private static final Log logger = LogFactory.get(); + + private static ProcessesForm processesForm; + private JPanel mainPanel; + private JTable processTable; + private JRadioButton cpuButton; + private JRadioButton cumulativeCpuButton; + private JRadioButton memButton; + private JRadioButton perProc; + private JRadioButton perSystem; + + public static ProcessesForm getInstance() { + if (processesForm == null) { + processesForm = new ProcessesForm(); + } + return processesForm; + } + + public static void init() { + processesForm = getInstance(); + + initUi(); + initInfo(); + } + + private static void initUi() { + resetCpuPercentButtonGroup(); + resetSortByButtonGroup(); + + processesForm = getInstance(); + if (SystemInfo.getCurrentPlatform().equals(PlatformEnum.WINDOWS)) { + processesForm.perSystem.setSelected(true); + } else { + processesForm.perProc.setSelected(true); + } + processesForm.cpuButton.setSelected(true); + + processesForm.perProc.addActionListener(e -> { + resetCpuPercentButtonGroup(); + processesForm.perProc.setSelected(true); + }); + processesForm.perSystem.addActionListener(e -> { + resetCpuPercentButtonGroup(); + processesForm.perSystem.setSelected(true); + }); + + processesForm.cpuButton.addActionListener(e -> { + resetSortByButtonGroup(); + processesForm.cpuButton.setSelected(true); + }); + processesForm.cumulativeCpuButton.addActionListener(e -> { + resetSortByButtonGroup(); + processesForm.cumulativeCpuButton.setSelected(true); + }); + processesForm.memButton.addActionListener(e -> { + resetSortByButtonGroup(); + processesForm.memButton.setSelected(true); + }); + } + + /** + * Codes are copied from oshi and have some modifications. + */ + private static void initInfo() { + OperatingSystem os = App.si.getOperatingSystem(); + TableModel model = new DefaultTableModel(parseProcesses(os.getProcesses(null, null, 0), App.si), COLUMNS) { + @Override + public Class getColumnClass(int column) { + if (column == 0) { + + return ImageIcon.class; + } + return Object.class; + } + }; + JTable procTable = getInstance().getProcessTable(); + procTable.setModel(model); + resizeColumns(procTable.getColumnModel()); + procTable.getColumnModel().getColumn(0).setMaxWidth(32); + procTable.getColumnModel().getColumn(0).setMinWidth(32); + procTable.setShowGrid(true); + + DefaultTableCellRenderer hr = (DefaultTableCellRenderer) procTable.getTableHeader() + .getDefaultRenderer(); + // The name of header column turn to left + hr.setHorizontalAlignment(DefaultTableCellRenderer.LEFT); + + Timer timer = new Timer(UiConsts.REFRESH_SLOW, e -> { + DefaultTableModel tableModel = (DefaultTableModel) procTable.getModel(); + Object[][] newData = parseProcesses(os.getProcesses(null, null, 0), App.si); + int rowCount = tableModel.getRowCount(); + for (int row = 0; row < newData.length; row++) { + if (row < rowCount) { + // Overwrite row + for (int col = 0; col < newData[row].length; col++) { + tableModel.setValueAt(newData[row][col], row, col); + } + } else { + // Add row + tableModel.addRow(newData[row]); + } + } + // Delete any extra rows + for (int row = rowCount - 1; row >= newData.length; row--) { + tableModel.removeRow(row); + } + }); + timer.start(); + } + + /** + * Codes are copied from oshi and have some modifications. + * + * @param list + * @param si + * @return + */ + private static Object[][] parseProcesses(List list, SystemInfo si) { + processesForm = getInstance(); + long totalMem = si.getHardware().getMemory().getTotal(); + int cpuCount = si.getHardware().getProcessor().getLogicalProcessorCount(); + // Build a map with a value for each process to control the sort + Map processSortValueMap = new HashMap<>(); + for (OSProcess p : list) { + int pid = p.getProcessID(); + // Ignore the Idle process on Windows + if (pid > 0 || !SystemInfo.getCurrentPlatform().equals(PlatformEnum.WINDOWS)) { + // Set up for appropriate sort + if (processesForm.cpuButton.isSelected()) { + processSortValueMap.put(p, p.getProcessCpuLoadBetweenTicks(priorSnapshotMap.get(pid))); + } else if (processesForm.cumulativeCpuButton.isSelected()) { + processSortValueMap.put(p, p.getProcessCpuLoadCumulative()); + } else { + processSortValueMap.put(p, (double) p.getResidentSetSize()); + } + } + } + // Now sort the list by the values + List> procList = new ArrayList<>(processSortValueMap.entrySet()); + procList.sort(Map.Entry.comparingByValue()); + // Insert into array in reverse order (lowest sort value last) + int i = procList.size(); + Object[][] procArr = new Object[i][COLUMNS.length]; + // These are in descending CPU order + for (Map.Entry e : procList) { + OSProcess p = e.getKey(); + // Matches order of COLUMNS field + i--; + int pid = p.getProcessID(); + procArr[i][0] = getProcessIcon(p.getPath()); + procArr[i][1] = pid; + procArr[i][2] = p.getParentProcessID(); + procArr[i][3] = p.getThreadCount(); + if (processesForm.perProc.isSelected()) { + procArr[i][4] = String.format("%.1f", + 100d * p.getProcessCpuLoadBetweenTicks(priorSnapshotMap.get(pid)) / cpuCount); + procArr[i][5] = String.format("%.1f", 100d * p.getProcessCpuLoadCumulative() / cpuCount); + } else { + procArr[i][4] = String.format("%.1f", + 100d * p.getProcessCpuLoadBetweenTicks(priorSnapshotMap.get(pid))); + procArr[i][5] = String.format("%.1f", 100d * p.getProcessCpuLoadCumulative()); + } + procArr[i][6] = FormatUtil.formatBytes(p.getVirtualSize()); + procArr[i][7] = FormatUtil.formatBytes(p.getResidentSetSize()); + procArr[i][8] = String.format("%.1f", 100d * p.getResidentSetSize() / totalMem); + procArr[i][9] = p.getName(); + } + // Re-populate snapshot map + priorSnapshotMap.clear(); + for (OSProcess p : list) { + priorSnapshotMap.put(p.getProcessID(), p); + } + return procArr; + } + + /** + * Retrieves the executable's associated icon if available, or returns null. + * + * @param fullProcessPathName The full path of the executable process. + * @return The associated icon, or null if not found. + */ + private static Icon getProcessIcon(String fullProcessPathName) { + if (iconCacheMap.containsKey(fullProcessPathName)) { + return iconCacheMap.get(fullProcessPathName); + } + + File file = new File(fullProcessPathName); + if (!file.exists()) { + // Alternatively, provide a default icon or return nul + return UIManager.getIcon("FileView.fileIcon"); + } + + try { + if (SystemUtil.isWindowsOs()) { + Icon icon = FileSystemView.getFileSystemView().getSystemIcon(file); + iconCacheMap.put(fullProcessPathName, icon); + return icon; + } + + if (SystemUtil.isLinuxOs()) { + // investigate why getPath or getCommandLine is "" on kali + } + + // macOS-specific icon retrieval + // maybe find a simpler solution + // Todo : fix various icons like VLC ... + if (SystemUtil.isMacOs() && fullProcessPathName.contains("MacOS")) { + String iconPathSplit = fullProcessPathName.split("MacOS")[0]; + String plistFilePath = iconPathSplit + "Info.plist"; + + File pListFile = getFileWithSpaceUri(plistFilePath); + if (pListFile.exists()) { + Map properties = Plist.load(plistFilePath); + String cFBundleIconFile = (String) properties.get("CFBundleIconFile"); + String iconFilePath = iconPathSplit + "Resources/" + cFBundleIconFile; + + // Ensure file path ends with ".icns" + if (!iconFilePath.endsWith(".icns")) { + iconFilePath += ".icns"; + } + + File iconFile = getFileWithSpaceUri(iconFilePath); + if (iconFile.canRead()) { + List iconImages = new IcnsImageParser().getAllBufferedImages(iconFile); + Optional resultImage = iconImages + .stream().parallel() + .filter(num -> num.getRaster().getHeight() == 32).findAny(); + + if (resultImage.isPresent()) { + BufferedImage bufferedImageR = resizeImage(resultImage.get(), 26, 26); + Icon icon = new ImageIcon(bufferedImageR); + iconCacheMap.put(fullProcessPathName, icon); + return icon; + } + + } + } + } + } catch (Exception e) { + } + return UIManager.getIcon("FileView.fileIcon"); + } + + /** + * Workaround to open folders files with spaces + * @param filePath + * @return file + */ + private static File getFileWithSpaceUri(String filePath) throws URISyntaxException { + URI outputURI = new URI(("file:///" + filePath.replaceAll(" ", "%20"))); + File outputFile = new File(outputURI); + return outputFile; + } + + /** + * ResizeImage BufferedImage to given targetWidth targetHeight preserve transparency + * + * @param originalImage + * @param targetWidth + * @param targetHeight + * @return resizeImage + */ + public static BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) throws IOException { + BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_ARGB_PRE); + Graphics2D graphics2D = resizedImage.createGraphics(); + graphics2D.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null); + graphics2D.dispose(); + return resizedImage; + } + + + /** + * Codes are copied from oshi and have some modifications. + * + * @param tableColumnModel + */ + private static void resizeColumns(TableColumnModel tableColumnModel) { + TableColumn column; + int tW = tableColumnModel.getTotalColumnWidth(); + int cantCols = tableColumnModel.getColumnCount(); + for (int i = 0; i < cantCols; i++) { + column = tableColumnModel.getColumn(i); + int pWidth = (int) Math.round(COLUMN_WIDTH_PERCENT[i] * tW); + column.setPreferredWidth(pWidth); + } + } + + private static void resetSortByButtonGroup() { + processesForm = getInstance(); + + processesForm.cpuButton.setSelected(false); + processesForm.cumulativeCpuButton.setSelected(false); + processesForm.memButton.setSelected(false); + } + + private static void resetCpuPercentButtonGroup() { + processesForm = getInstance(); + + processesForm.perProc.setSelected(false); + processesForm.perSystem.setSelected(false); + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + mainPanel = new JPanel(); + mainPanel.setLayout(new GridLayoutManager(2, 1, new Insets(20, 20, 20, 20), -1, -1)); + final JScrollPane scrollPane1 = new JScrollPane(); + mainPanel.add(scrollPane1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + processTable = new JTable(); + scrollPane1.setViewportView(processTable); + final JPanel panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(1, 8, new Insets(0, 0, 10, 0), -1, -1)); + mainPanel.add(panel1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JLabel label1 = new JLabel(); + label1.setText("Sort by: "); + panel1.add(label1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + panel1.add(spacer1, new GridConstraints(0, 4, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final JLabel label2 = new JLabel(); + label2.setText("CPU %: "); + panel1.add(label2, new GridConstraints(0, 5, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + cpuButton = new JRadioButton(); + cpuButton.setText("CPU %"); + panel1.add(cpuButton, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + cumulativeCpuButton = new JRadioButton(); + cumulativeCpuButton.setText("Cumulative CPU"); + panel1.add(cumulativeCpuButton, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + memButton = new JRadioButton(); + memButton.setText("Memory %"); + panel1.add(memButton, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + perProc = new JRadioButton(); + perProc.setText("of one Processor"); + panel1.add(perProc, new GridConstraints(0, 6, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + perSystem = new JRadioButton(); + perSystem.setText("of System"); + panel1.add(perSystem, new GridConstraints(0, 7, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return mainPanel; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/UsbForm.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/UsbForm.form new file mode 100644 index 0000000..7f7e4b0 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/UsbForm.form @@ -0,0 +1,38 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/UsbForm.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/UsbForm.java new file mode 100644 index 0000000..323d0f9 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/UsbForm.java @@ -0,0 +1,107 @@ +package io.fluent.pcinfo.ui.form; + +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; + +import io.fluent.pcinfo.App; +import lombok.Getter; +import oshi.hardware.HardwareAbstractionLayer; +import oshi.hardware.UsbDevice; + +import javax.swing.*; +import java.awt.*; + +/** + * UsbForm + * + * @author RememBerBer + * @since 2021/11/12. + */ +@Getter +public class UsbForm { + + private static final Log logger = LogFactory.get(); + + private static UsbForm usbForm; + private JPanel mainPanel; + private JTextPane infoPane; + + public static UsbForm getInstance() { + if (usbForm == null) { + usbForm = new UsbForm(); + } + return usbForm; + } + + public static void init() { + usbForm = getInstance(); + + initUi(); + initInfo(); + } + + private static void initUi() { + } + + private static void initInfo() { + JTextPane infoPane = getInstance().getInfoPane(); + infoPane.setText(getUsbString(App.si.getHardware())); + } + + /** + * Codes are copied from oshi and have some modifications. + * + * @param hal + * @return + */ + private static String getUsbString(HardwareAbstractionLayer hal) { + StringBuilder sb = new StringBuilder(); + boolean first = true; + for (UsbDevice usbDevice : hal.getUsbDevices(true)) { + if (first) { + first = false; + } else { + sb.append('\n'); + } + sb.append(usbDevice); + } + return sb.toString(); + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + mainPanel = new JPanel(); + mainPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + final JPanel panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(1, 1, new Insets(20, 20, 20, 20), -1, -1)); + mainPanel.add(panel1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final JScrollPane scrollPane1 = new JScrollPane(); + panel1.add(scrollPane1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + infoPane = new JTextPane(); + infoPane.setEditable(false); + scrollPane1.setViewportView(infoPane); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return mainPanel; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/VariablesForm.form b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/VariablesForm.form new file mode 100644 index 0000000..8e18ca1 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/VariablesForm.form @@ -0,0 +1,95 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/VariablesForm.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/VariablesForm.java new file mode 100644 index 0000000..9064caf --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/form/VariablesForm.java @@ -0,0 +1,166 @@ +package io.fluent.pcinfo.ui.form; + +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.uiDesigner.core.GridLayoutManager; +import com.intellij.uiDesigner.core.Spacer; +import io.fluent.pcinfo.App; +import lombok.Getter; + +import javax.swing.*; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; +import java.awt.*; +import java.util.Map; +import java.util.Properties; + +/** + * VariablesForm + * + * @author RememBerBer + * @since 2021/11/12. + */ +@Getter +public class VariablesForm { + private static final Log logger = LogFactory.get(); + + private static VariablesForm variablesForm; + private JPanel mainPanel; + private JTable sysEnvVarTable; + private JTable javaPropsTable; + private JLabel sysEnvLabel; + private JLabel javaPropLabel; + + private static final double[] COLUMN_WIDTH_PERCENT = {0.38, 0.62}; + + public static VariablesForm getInstance() { + if (variablesForm == null) { + variablesForm = new VariablesForm(); + } + return variablesForm; + } + + public static void init() { + variablesForm = getInstance(); + + initUi(); + initInfo(); + } + + private static void initUi() { + getInstance().getSysEnvVarTable().setShowGrid(true); + getInstance().getJavaPropsTable().setShowGrid(true); + + Font emphaticFont = new Font(getInstance().getMainPanel().getFont().getName(), Font.BOLD, getInstance().getMainPanel().getFont().getSize() + 2); + getInstance().getSysEnvLabel().setFont(emphaticFont); + getInstance().getJavaPropLabel().setFont(emphaticFont); + } + + private static void initInfo() { + initSysEnvVarTable(); + initJavaPropsTable(); + } + + public static void initSysEnvVarTable() { + String[] headerNames = {"Key", "Value"}; + DefaultTableModel model = new DefaultTableModel(null, headerNames); + + Map map = System.getenv(); + Object[] data; + for (Map.Entry envEntry : map.entrySet()) { + data = new Object[2]; + data[0] = envEntry.getKey(); + data[1] = envEntry.getValue(); + model.addRow(data); + } + + JTable sysEnvVarTable = getInstance().getSysEnvVarTable(); + sysEnvVarTable.setModel(model); + resizeColumns(sysEnvVarTable.getColumnModel()); + } + + public static void initJavaPropsTable() { + String[] headerNames = {"Key", "Value"}; + DefaultTableModel model = new DefaultTableModel(null, headerNames); + + Properties properties = System.getProperties(); + Object[] data; + for (Map.Entry objectObjectEntry : properties.entrySet()) { + data = new Object[2]; + data[0] = objectObjectEntry.getKey(); + data[1] = objectObjectEntry.getValue(); + model.addRow(data); + } + + JTable javaPropsTable = getInstance().getJavaPropsTable(); + javaPropsTable.setModel(model); + resizeColumns(javaPropsTable.getColumnModel()); + } + + private static void resizeColumns(TableColumnModel tableColumnModel) { + TableColumn column; + int tW = App.mainFrame.getWidth() - 20; + int cantCols = tableColumnModel.getColumnCount(); + for (int i = 0; i < cantCols; i++) { + column = tableColumnModel.getColumn(i); + int pWidth = (int) Math.round(COLUMN_WIDTH_PERCENT[i] * tW); + column.setPreferredWidth(pWidth); + } + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + mainPanel = new JPanel(); + mainPanel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1)); + final JPanel panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(4, 1, new Insets(20, 20, 20, 20), -1, -1)); + mainPanel.add(panel1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + final JPanel panel2 = new JPanel(); + panel2.setLayout(new GridLayoutManager(1, 2, new Insets(10, 0, 0, 0), -1, -1)); + panel1.add(panel2, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + sysEnvLabel = new JLabel(); + sysEnvLabel.setText("System environment variables"); + panel2.add(sysEnvLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + panel2.add(spacer1, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final JScrollPane scrollPane1 = new JScrollPane(); + panel1.add(scrollPane1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + sysEnvVarTable = new JTable(); + scrollPane1.setViewportView(sysEnvVarTable); + final JPanel panel3 = new JPanel(); + panel3.setLayout(new GridLayoutManager(1, 2, new Insets(10, 0, 0, 0), -1, -1)); + panel1.add(panel3, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + javaPropLabel = new JLabel(); + javaPropLabel.setText("Java properties"); + panel3.add(javaPropLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer2 = new Spacer(); + panel3.add(spacer2, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + final JScrollPane scrollPane2 = new JScrollPane(); + panel1.add(scrollPane2, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + javaPropsTable = new JTable(); + scrollPane2.setViewportView(javaPropsTable); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return mainPanel; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/frame/MainFrame.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/frame/MainFrame.java new file mode 100644 index 0000000..014b729 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/frame/MainFrame.java @@ -0,0 +1,42 @@ +package io.fluent.pcinfo.ui.frame; + +import com.formdev.flatlaf.extras.FlatSVGUtils; +import com.formdev.flatlaf.util.SystemInfo; +import io.fluent.pcinfo.ui.UiConsts; +import io.fluent.pcinfo.ui.component.TopMenuBar; +import io.fluent.pcinfo.ui.listener.FrameListener; +import io.fluent.pcinfo.util.ComponentUtil; +import io.fluent.pcinfo.util.SystemUtil; + + +import javax.swing.*; + +/** + * Main Frame + * + * @author RememBerBer + * @since 2021/11/08. + */ +public class MainFrame extends JFrame { + + public void init() { + this.setName(UiConsts.APP_NAME); + this.setTitle(UiConsts.APP_NAME); +// FrameUtil.setFrameIcon(this); + setIconImages(FlatSVGUtils.createWindowIconImages("/icons/MooInfo.svg")); + TopMenuBar topMenuBar = TopMenuBar.getInstance(); + topMenuBar.init(); + setJMenuBar(topMenuBar); + ComponentUtil.setPreferSizeAndLocateToCenter(this, 0.6, 0.8); + + if (SystemUtil.isMacOs() && SystemInfo.isMacFullWindowContentSupported) { + this.getRootPane().putClientProperty("apple.awt.fullWindowContent", true); + this.getRootPane().putClientProperty("apple.awt.transparentTitleBar", true); + this.getRootPane().putClientProperty("apple.awt.fullscreenable", true); + this.getRootPane().putClientProperty("apple.awt.windowTitleVisible", false); + } + + FrameListener.addListeners(); + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/listener/FrameListener.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/listener/FrameListener.java new file mode 100644 index 0000000..e137d88 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/ui/listener/FrameListener.java @@ -0,0 +1,104 @@ +package io.fluent.pcinfo.ui.listener; + + + +import io.fluent.pcinfo.App; +import io.fluent.pcinfo.ui.Init; +import io.fluent.pcinfo.util.SystemUtil; + +import javax.swing.*; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; + +/** + * Form event monitoring + * + * @author RememBerBer + * @since 2021/11/10. + */ +public class FrameListener { + + + public static void addListeners() { + App.mainFrame.addWindowListener(new WindowListener() { + + @Override + public void windowOpened(WindowEvent e) { + + } + + @Override + public void windowIconified(WindowEvent e) { + + } + + @Override + public void windowDeiconified(WindowEvent e) { + + } + + @Override + public void windowDeactivated(WindowEvent e) { + + } + + @Override + public void windowClosing(WindowEvent e) { + if (SystemUtil.isWindowsOs()) { + App.mainFrame.setVisible(false); + } else { + App.mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + } + + Init.shutdown(); + } + + @Override + public void windowClosed(WindowEvent e) { + + } + + @Override + public void windowActivated(WindowEvent e) { + + } + }); + + App.mainFrame.addMouseListener(new MouseListener() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2 && !e.isConsumed()) { + if (App.mainFrame.getExtendedState() == JFrame.MAXIMIZED_BOTH) { + App.mainFrame.setExtendedState(JFrame.NORMAL); + } else { + App.mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH); + } + } + } + + @Override + public void mousePressed(MouseEvent e) { + + } + + @Override + public void mouseReleased(MouseEvent e) { + + } + + @Override + public void mouseEntered(MouseEvent e) { + + } + + @Override + public void mouseExited(MouseEvent e) { + + } + }); + + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/ComponentUtil.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/ComponentUtil.java new file mode 100644 index 0000000..8bc9763 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/ComponentUtil.java @@ -0,0 +1,41 @@ +package io.fluent.pcinfo.util; + + +import io.fluent.pcinfo.App; + +import java.awt.*; + +/** + * util for swing component + * + * @author RememBerBer + * @since 2021/11/08. + */ +public class ComponentUtil { + private static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + private static Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(App.mainFrame.getGraphicsConfiguration()); + + private static int screenWidth = screenSize.width - screenInsets.left - screenInsets.right; + + private static int screenHeight = screenSize.height - screenInsets.top - screenInsets.bottom; + + /** + * Set up the component preferSize and position it in the center of the screen + */ + public static void setPreferSizeAndLocateToCenter(Component component, int preferWidth, int preferHeight) { + component.setBounds((screenWidth - preferWidth) / 2, (screenHeight - preferHeight) / 2, + preferWidth, preferHeight); + Dimension preferSize = new Dimension(preferWidth, preferHeight); + component.setPreferredSize(preferSize); + } + + /** + * Set the component preferSize and position it in the center of the screen (based on the percentage of screen width) + */ + public static void setPreferSizeAndLocateToCenter(Component component, double preferWidthPercent, double preferHeightPercent) { + int preferWidth = (int) (screenWidth * preferWidthPercent); + int preferHeight = (int) (screenHeight * preferHeightPercent); + setPreferSizeAndLocateToCenter(component, preferWidth, preferHeight); + } +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/ConfigBaseUtil.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/ConfigBaseUtil.java new file mode 100644 index 0000000..0a516ee --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/ConfigBaseUtil.java @@ -0,0 +1,41 @@ +package io.fluent.pcinfo.util; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.setting.Setting; + +import java.io.File; + +/** + * Base class of configuration management + * + * @author RememBerBer + * @since 2021/11/08. + */ +public class ConfigBaseUtil { + /** + * path of the setting file + */ + private String settingFilePath = SystemUtil.CONFIG_HOME + File.separator + "config" + File.separator + "config.setting"; + + Setting setting; + + ConfigBaseUtil() { + setting = new Setting(FileUtil.touch(settingFilePath), CharsetUtil.CHARSET_UTF_8, false); + } + + public void setProps(String key, String value) { + setting.put(key, value); + } + + public String getProps(String key) { + return setting.get(key); + } + + /** + * save to disk + */ + public void save() { + setting.store(settingFilePath); + } +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/ConfigUtil.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/ConfigUtil.java new file mode 100644 index 0000000..abc9975 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/ConfigUtil.java @@ -0,0 +1,97 @@ +package io.fluent.pcinfo.util; + +/** + * Configuration management + * + * @author RememBerBer + * @since 2021/11/08. + */ +public class ConfigUtil extends ConfigBaseUtil { + + private static final ConfigUtil configUtil = new ConfigUtil(); + + public static ConfigUtil getInstance() { + return configUtil; + } + + private ConfigUtil() { + super(); + } + + private boolean autoCheckUpdate; + + private boolean defaultMaxWindow; + + private boolean unifiedBackground; + + private String beforeVersion; + + private String theme; + + private String font; + + private int fontSize; + + public boolean isAutoCheckUpdate() { + return setting.getBool("autoCheckUpdate", "setting.common", true); + } + + public void setAutoCheckUpdate(boolean autoCheckUpdate) { + setting.putByGroup("autoCheckUpdate", "setting.common", String.valueOf(autoCheckUpdate)); + } + + public boolean isDefaultMaxWindow() { + return setting.getBool("defaultMaxWindow", "setting.normal", false); + } + + public void setDefaultMaxWindow(boolean defaultMaxWindow) { + setting.putByGroup("defaultMaxWindow", "setting.normal", String.valueOf(defaultMaxWindow)); + } + + public boolean isUnifiedBackground() { + return setting.getBool("unifiedBackground", "setting.normal", true); + } + + public void setUnifiedBackground(boolean unifiedBackground) { + setting.putByGroup("unifiedBackground", "setting.normal", String.valueOf(unifiedBackground)); + } + + public String getBeforeVersion() { + return setting.getStr("beforeVersion", "setting.common", "0.0.0"); + } + + public void setBeforeVersion(String beforeVersion) { + setting.putByGroup("beforeVersion", "setting.common", beforeVersion); + } + + public String getTheme() { + return setting.getStr("theme", "setting.appearance", "Dark purple"); + } + + public void setTheme(String theme) { + setting.putByGroup("theme", "setting.appearance", theme); + } + + public String getFont() { + if (SystemUtil.isLinuxOs()) { + return setting.getStr("font", "setting.appearance", "Noto Sans CJK HK"); + } else if (SystemUtil.isMacOs()) { + return setting.getStr("font", "setting.appearance", "PingFang SC"); + } else { + return setting.getStr("font", "setting.appearance", "Microsoft YaHei"); + } + } + + public void setFont(String font) { + setting.putByGroup("font", "setting.appearance", font); + } + + public int getFontSize() { + return setting.getInt("fontSize", "setting.appearance", 13); + } + + public void setFontSize(int fontSize) { + setting.putByGroup("fontSize", "setting.appearance", String.valueOf(fontSize)); + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/ConsoleUtil.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/ConsoleUtil.java new file mode 100644 index 0000000..74105e1 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/ConsoleUtil.java @@ -0,0 +1,36 @@ +package io.fluent.pcinfo.util; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import lombok.extern.slf4j.Slf4j; + +import javax.swing.*; +import java.util.Date; + +/** + *
+ * ConsoleUtil to print text into textarea
+ * 
+ * + * @author RememBerBer + * @since 2021/12/15. + */ +@Slf4j +public class ConsoleUtil { + + private static final Log logger = LogFactory.get(); + + public static void consoleWithLog(JTextArea textArea, String log) { + textArea.append(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss.SSS") + " "); + textArea.append(log + "\n"); + textArea.setCaretPosition(textArea.getText().length()); + logger.warn(log); + } + + public static void consoleOnly(JTextArea textArea, String log) { + textArea.append(log + "\n"); + textArea.setCaretPosition(textArea.getText().length()); + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/DateTimeUtil.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/DateTimeUtil.java new file mode 100644 index 0000000..4c6953b --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/DateTimeUtil.java @@ -0,0 +1,14 @@ +package io.fluent.pcinfo.util; + +public class DateTimeUtil { + + public static String toReadableTime(long seconds) { + String readableTime; + int hours = (int) (seconds / 3600); + int minutes = (int) (seconds % 3600 / 60); + readableTime = String.format("%dh:%02dmin", hours, minutes); + + return readableTime; + } + +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/FrameUtil.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/FrameUtil.java new file mode 100644 index 0000000..f6d427b --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/FrameUtil.java @@ -0,0 +1,33 @@ +package io.fluent.pcinfo.util; + +import io.fluent.pcinfo.ui.UiConsts; + +import javax.swing.*; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +/** + *
+ * FrameUtil
+ * 
+ * + * @author RememBerBer + * @since 2021/11/08. + */ +public class FrameUtil { + + public static void setFrameIcon(JFrame jFrame) { + List images = new ArrayList<>(); + images.add(UiConsts.IMAGE_LOGO_1024); + images.add(UiConsts.IMAGE_LOGO_512); + images.add(UiConsts.IMAGE_LOGO_256); + images.add(UiConsts.IMAGE_LOGO_128); + images.add(UiConsts.IMAGE_LOGO_64); + images.add(UiConsts.IMAGE_LOGO_48); + images.add(UiConsts.IMAGE_LOGO_32); + images.add(UiConsts.IMAGE_LOGO_24); + images.add(UiConsts.IMAGE_LOGO_16); + jFrame.setIconImages(images); + } +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/ScrollUtil.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/ScrollUtil.java new file mode 100644 index 0000000..9c763f8 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/ScrollUtil.java @@ -0,0 +1,19 @@ +package io.fluent.pcinfo.util; + +import javax.swing.*; + +/** + * some functions about scroll + * + * @author RememBerBer + * @since 2021/11/23. + */ +public class ScrollUtil { + + public static void smoothPane(JScrollPane scrollPane) { + scrollPane.getVerticalScrollBar().setUnitIncrement(14); + scrollPane.getHorizontalScrollBar().setUnitIncrement(14); + scrollPane.getVerticalScrollBar().setDoubleBuffered(true); + scrollPane.getHorizontalScrollBar().setDoubleBuffered(true); + } +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/SystemUtil.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/SystemUtil.java new file mode 100644 index 0000000..4a8d454 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/SystemUtil.java @@ -0,0 +1,42 @@ +package io.fluent.pcinfo.util; + +import java.io.File; + +/** + * System util + * + * @author RememBerBer + * @since 2021/11/08. + */ +public class SystemUtil { + private static final String OS_NAME = System.getProperty("os.name"); + private static final String OS_ARCH = System.getProperty("os.arch"); + private static final String VM_VENDOR = System.getProperty("java.vm.vendor"); + private static final String USER_HOME = System.getProperty("user.home"); + public static final String CONFIG_HOME = USER_HOME + File.separator + ".MooInfo"; + + /** + * log file dir + */ + public final static String LOG_DIR = USER_HOME + File.separator + ".MooInfo" + File.separator + "logs" + File.separator; + + public static boolean isMacOs() { + return OS_NAME.contains("Mac"); + } + + public static boolean isMacM1() { + return OS_NAME.contains("Mac") && "aarch64".equals(OS_ARCH); + } + + public static boolean isWindowsOs() { + return OS_NAME.contains("Windows"); + } + + public static boolean isLinuxOs() { + return OS_NAME.contains("Linux"); + } + + public static boolean isJBR() { + return VM_VENDOR.contains("JetBrains"); + } +} \ No newline at end of file diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/UIUtil.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/UIUtil.java new file mode 100644 index 0000000..fa6e554 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/UIUtil.java @@ -0,0 +1,65 @@ +package io.fluent.pcinfo.util; + +import io.fluent.pcinfo.App; +import lombok.extern.slf4j.Slf4j; + +import java.awt.*; + +/** + * UI custom tools + * + * @author RememBerBer + * @since 2021/11/10. + */ +@Slf4j +public class UIUtil { + + /** + * Get screen specifications + *

+ * author by darcula@com.bulenkov + * see https://github.com/bulenkov/Darcula + * + * @return + */ + public static float getScreenScale() { + int dpi = 96; + + try { + dpi = Toolkit.getDefaultToolkit().getScreenResolution(); + } catch (HeadlessException var2) { + } + + float scale = 1.0F; + if (dpi < 120) { + scale = 1.0F; + } else if (dpi < 144) { + scale = 1.25F; + } else if (dpi < 168) { + scale = 1.5F; + } else if (dpi < 192) { + scale = 1.75F; + } else { + scale = 2.0F; + } + + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + log.info("screen dpi:{},width:{},height:{}", dpi, screenSize.getWidth(), screenSize.getHeight()); + + return scale; + } + + /** + * the theme is dark or not + * + * @return + */ + public static boolean isDarkLaf() { + return "Darcula".equals(App.config.getTheme()) + || "Darcula(Recommended)".equals(App.config.getTheme()) + || "Flat Dark".equals(App.config.getTheme()) + || "Flat Darcula".equals(App.config.getTheme()) + || "Dark purple".equals(App.config.getTheme()) + || "Flat Darcula(Recommended)".equals(App.config.getTheme()); + } +} diff --git a/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/UpgradeUtil.java b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/UpgradeUtil.java new file mode 100644 index 0000000..cab1f55 --- /dev/null +++ b/fluent-apps/pcinfo/src/main/java/io/fluent/pcinfo/util/UpgradeUtil.java @@ -0,0 +1,136 @@ +package io.fluent.pcinfo.util; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONUtil; +import io.fluent.pcinfo.App; +import io.fluent.pcinfo.bean.VersionSummary; +import io.fluent.pcinfo.ui.UiConsts; +import io.fluent.pcinfo.ui.dialog.UpdateInfoDialog; +import lombok.extern.slf4j.Slf4j; + +import javax.swing.*; +import java.util.List; +import java.util.Map; + +/** + * Upgrade tool class + * + * @author RememBerBer + * @since 2021/11/08. + */ +@Slf4j +public class UpgradeUtil { + + public static void checkUpdate(boolean initCheck) { + // current version + String currentVersion = UiConsts.APP_VERSION; + + // Get information about the latest version from github + String versionSummaryJsonContent = HttpUtil.get(UiConsts.CHECK_VERSION_URL); + if (StrUtil.isEmpty(versionSummaryJsonContent) && !initCheck) { + JOptionPane.showMessageDialog(App.mainFrame, + "Check for timeouts, follow GitHub Release!", "Network error", + JOptionPane.INFORMATION_MESSAGE); + return; + } else if (StrUtil.isEmpty(versionSummaryJsonContent) || versionSummaryJsonContent.contains("404: Not Found")) { + return; + } + versionSummaryJsonContent = versionSummaryJsonContent.replace("\n", ""); + + VersionSummary versionSummary = JSONUtil.toBean(versionSummaryJsonContent, VersionSummary.class); + // The latest version + String newVersion = versionSummary.getCurrentVersion(); + String versionIndexJsonContent = versionSummary.getVersionIndex(); + // Version index + Map versionIndexMap = JSONUtil.toBean(versionIndexJsonContent, Map.class); + // list of version details + List versionDetailList = versionSummary.getVersionDetailList(); + + if (newVersion.compareTo(currentVersion) > 0) { + // The current version index + int currentVersionIndex = Integer.parseInt(versionIndexMap.get(currentVersion)); + // Version update log: + StringBuilder versionLogBuilder = new StringBuilder("

Surprise the new version! Download it now?

"); + VersionSummary.Version version; + for (int i = currentVersionIndex + 1; i < versionDetailList.size(); i++) { + version = versionDetailList.get(i); + versionLogBuilder.append("

").append(version.getVersion()).append("

"); + versionLogBuilder.append("").append(version.getTitle()).append("
"); + versionLogBuilder.append("

").append(version.getLog().replaceAll("\\n", "

")).append("

"); + } + String versionLog = versionLogBuilder.toString(); + + UpdateInfoDialog updateInfoDialog = new UpdateInfoDialog(); + updateInfoDialog.setHtmlText(versionLog); + updateInfoDialog.setNewVersion(newVersion); + updateInfoDialog.pack(); + updateInfoDialog.setVisible(true); + } else { + if (!initCheck) { + JOptionPane.showMessageDialog(App.mainFrame, + "It's the latest version!", "Congratulations", + JOptionPane.INFORMATION_MESSAGE); + } + } + } + + /** + * Smooth upgrade + * The version update scripts and sql methods involved are as idempotent as possible to avoid repeated upgrade operations due to unusual interruptions such as power failures and deaths during the upgrade process + */ + public static void smoothUpgrade() { + // Get the current version + String currentVersion = UiConsts.APP_VERSION; + // Get the before upgrade version + String beforeVersion = App.config.getBeforeVersion(); + + if (currentVersion.compareTo(beforeVersion) <= 0) { + // If both are consistent, no upgrade action is performed + return; + } else { + log.info("Smooth upgrade begins"); + + // Then take the index for both versions + String versionSummaryJsonContent = FileUtil.readString(UiConsts.class.getResource("/version_summary.json"), CharsetUtil.UTF_8); + versionSummaryJsonContent = versionSummaryJsonContent.replace("\n", ""); + VersionSummary versionSummary = JSONUtil.toBean(versionSummaryJsonContent, VersionSummary.class); + String versionIndex = versionSummary.getVersionIndex(); + Map versionIndexMap = JSONUtil.toBean(versionIndex, Map.class); + int currentVersionIndex = Integer.parseInt(versionIndexMap.get(currentVersion)); + int beforeVersionIndex = Integer.parseInt(versionIndexMap.get(beforeVersion)); + log.info("Older version{}", beforeVersion); + log.info("Current version{}", currentVersion); + // Traverses the index range + beforeVersionIndex++; + for (int i = beforeVersionIndex; i <= currentVersionIndex; i++) { + log.info("Update the version index {} begin", i); + // Perform updates to each version index, from far to nearby time + upgrade(i); + log.info("Update the version index {} finished", i); + } + + // If the upgrade is complete and successful, the version number prior to the upgrade is assigned to the current version + App.config.setBeforeVersion(currentVersion); + App.config.save(); + log.info("Smooth upgrade ends"); + } + } + + /** + * Execute the upgrade script + * + * @param versionIndex Version index + */ + private static void upgrade(int versionIndex) { + log.info("Start with the upgrade script, version index:{}", versionIndex); + switch (versionIndex) { + case 21: + break; + default: + } + log.info("The upgrade script ends, the version index:{}", versionIndex); + } +} diff --git a/fluent-apps/pom.xml b/fluent-apps/pom.xml index db16297..4db3ace 100644 --- a/fluent-apps/pom.xml +++ b/fluent-apps/pom.xml @@ -12,7 +12,8 @@ fluent-apps pom - feeds + pcinfo + workspace diff --git a/fluent-apps/feeds/pom.xml b/fluent-apps/workspace/pom.xml similarity index 66% rename from fluent-apps/feeds/pom.xml rename to fluent-apps/workspace/pom.xml index 05344d0..e2e0407 100644 --- a/fluent-apps/feeds/pom.xml +++ b/fluent-apps/workspace/pom.xml @@ -9,11 +9,14 @@ 1.0-SNAPSHOT - feeds + workspace + 17 + 17 UTF-8 + @@ -32,7 +35,6 @@ erupt-job ${erupt.version} - xyz.erupt @@ -66,15 +68,57 @@ 4.4.0 + + io.fluent + fluent-excel + ${fluent.version} + + + io.fluent + fluent-mindmap + ${fluent.version} + + + io.fluent + fluent-erupts-base + ${fluent.version} + + io.fluent fleunt-github ${fluent.version} + + + + + cn.hutool hutool-all + + io.fluent + fluent-quickdao + 1.0-SNAPSHOT + + + io.fluent + fluent-openapi + 1.0-SNAPSHOT + + + + + + + + + + + + @@ -101,4 +145,5 @@ + \ No newline at end of file diff --git a/fluent-apps/feeds/src/main/java/io/fluent/datafam/DataFeedFarmApp.java b/fluent-apps/workspace/src/main/java/io/fluent/WorkspaceApplication.java similarity index 67% rename from fluent-apps/feeds/src/main/java/io/fluent/datafam/DataFeedFarmApp.java rename to fluent-apps/workspace/src/main/java/io/fluent/WorkspaceApplication.java index 1f83913..ba3e056 100644 --- a/fluent-apps/feeds/src/main/java/io/fluent/datafam/DataFeedFarmApp.java +++ b/fluent-apps/workspace/src/main/java/io/fluent/WorkspaceApplication.java @@ -1,4 +1,4 @@ -package io.fluent.datafam; +package io.fluent; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -10,8 +10,12 @@ @EnableAsync @EruptScan @EntityScan -public class DataFeedFarmApp { +public class WorkspaceApplication { + /** + * QA Management Application Entrypoint + * @param args + */ public static void main(String[] args) { - SpringApplication.run(DataFeedFarmApp.class); + SpringApplication.run(WorkspaceApplication.class); } } diff --git a/fluent-apps/workspace/src/main/java/io/fluent/base/FluentProductConfigModule.java b/fluent-apps/workspace/src/main/java/io/fluent/base/FluentProductConfigModule.java new file mode 100644 index 0000000..d4f42ec --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/base/FluentProductConfigModule.java @@ -0,0 +1,65 @@ +package io.fluent.base; + +import io.fluent.base.masterdata.model.MasterData; +import io.fluent.base.product.model.ProductModuleModel; +import io.fluent.base.project.model.ProjectModel; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import xyz.erupt.core.annotation.EruptScan; +import xyz.erupt.core.constant.MenuTypeEnum; +import xyz.erupt.core.module.EruptModule; +import xyz.erupt.core.module.EruptModuleInvoke; +import xyz.erupt.core.module.MetaMenu; +import xyz.erupt.core.module.ModuleInfo; + +import java.util.ArrayList; +import java.util.List; + +@Configuration +@ComponentScan +@EntityScan +@EruptScan +@EnableConfigurationProperties +public class FluentProductConfigModule implements EruptModule { + + public FluentProductConfigModule() { + } + + @Override + public ModuleInfo info() { + return ModuleInfo.builder().name("fluent-product").build(); + } + + @Override + public void run() { + EruptModule.super.run(); + } + + @Override + public List initMenus() { + List menus = new ArrayList<>(); + menus.add(MetaMenu.createRootMenu("$fluent-master", "产品配置", "fa fa-product-hunt", 90)); + MetaMenu productMetaMenu = MetaMenu.createEruptClassMenu(ProductModuleModel.class, menus.get(0), 0, MenuTypeEnum.TABLE); + productMetaMenu.setIcon("fa fa-group"); + productMetaMenu.setName("产品元数据"); + productMetaMenu.setCode("$product-meta"); + menus.add(productMetaMenu); + MetaMenu masterDataMenu = MetaMenu.createEruptClassMenu(MasterData.class, menus.get(0), 1, MenuTypeEnum.TABLE); + masterDataMenu.setIcon("fa fa-times"); + masterDataMenu.setName("产品字典表配置"); + masterDataMenu.setCode("$master-data"); + menus.add(masterDataMenu); + MetaMenu projectMenu = MetaMenu.createEruptClassMenu(ProjectModel.class, menus.get(0), 2, MenuTypeEnum.TABLE); + projectMenu.setIcon("fa fa-linode"); + projectMenu.setName("项目配置"); + projectMenu.setCode("$project-meta"); + menus.add(projectMenu); + return menus; + } + + static { + EruptModuleInvoke.addEruptModule(FluentProductConfigModule.class); + } +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/base/README.md b/fluent-apps/workspace/src/main/java/io/fluent/base/README.md new file mode 100644 index 0000000..9fb066c --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/base/README.md @@ -0,0 +1,8 @@ +# README + +shared component: + +- master data: shared configurations +- upload data: upload component +- product: product module +- project: project module \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/base/masterdata/model/MasterData.java b/fluent-apps/workspace/src/main/java/io/fluent/base/masterdata/model/MasterData.java new file mode 100644 index 0000000..e8d0150 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/base/masterdata/model/MasterData.java @@ -0,0 +1,76 @@ +package io.fluent.base.masterdata.model; + +import io.fluent.base.handlers.SqlTagFetchHandler; +import io.fluent.base.model.ModelWithValidFlagVo; +import lombok.Data; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.sub_edit.InputType; +import xyz.erupt.annotation.sub_field.sub_edit.Search; +import xyz.erupt.annotation.sub_field.sub_edit.TagsType; + +import javax.persistence.Entity; +import javax.persistence.Table; + + +@Erupt(name = "产品字典值配置", power = @Power(importable = true, export = true)) +@Table(name = "master_data") +@Entity +@Data +public class MasterData extends ModelWithValidFlagVo { + + @EruptField( + views = @View(title = "分类"), + edit = @Edit( + search = @Search(vague = true), + title = "获取可选种类", + type = EditType.TAGS, + desc = "动态获取可选种类", + tagsType = @TagsType( + fetchHandler = SqlTagFetchHandler.class, + fetchHandlerParams = "select distinct category from master_data where valid=true" + )) + ) + private String category; + + @EruptField( + views = @View( + title = "名称" + ), + edit = @Edit( + title = "名称", + type = EditType.INPUT, search = @Search, notNull = true, + inputType = @InputType + ) + ) + private String name; + + @EruptField( + views = @View( + title = "详细描述" + ), + edit = @Edit( + title = "详细描述", + type = EditType.INPUT, + inputType = @InputType + ) + ) + private String detail; + + @EruptField( + views = @View( + title = "代号" + ), + edit = @Edit( + title = "代号", + type = EditType.INPUT, search = @Search, notNull = true, + inputType = @InputType + ) + ) + private String code; + +} \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/base/masterdata/repo/MasterDataRepo.java b/fluent-apps/workspace/src/main/java/io/fluent/base/masterdata/repo/MasterDataRepo.java new file mode 100644 index 0000000..2618156 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/base/masterdata/repo/MasterDataRepo.java @@ -0,0 +1,15 @@ +package io.fluent.base.masterdata.repo; + +import io.fluent.base.masterdata.model.MasterData; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface MasterDataRepo extends JpaRepository, JpaSpecificationExecutor { + + Optional findMasterDataByCode(String code); + +} \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/base/package-info.java b/fluent-apps/workspace/src/main/java/io/fluent/base/package-info.java new file mode 100644 index 0000000..b1b2672 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/base/package-info.java @@ -0,0 +1 @@ +package io.fluent.base; \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/base/product/model/ProductModuleModel.java b/fluent-apps/workspace/src/main/java/io/fluent/base/product/model/ProductModuleModel.java new file mode 100644 index 0000000..a86390c --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/base/product/model/ProductModuleModel.java @@ -0,0 +1,140 @@ +package io.fluent.base.product.model; + +import io.fluent.base.model.ModelWithValidFlagVo; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_erupt.Tree; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.sub_edit.ChoiceType; +import xyz.erupt.annotation.sub_field.sub_edit.InputType; +import xyz.erupt.annotation.sub_field.sub_edit.ReferenceTreeType; +import xyz.erupt.annotation.sub_field.sub_edit.Search; +import xyz.erupt.toolkit.handler.SqlChoiceFetchHandler; + +import javax.persistence.*; +import java.util.UUID; + +@Erupt(name = "产品模块配置", + power = @Power(importable = true, export = true), + tree = @Tree(pid = "parent.id")) +@Entity +@Table(name = "products") +public class ProductModuleModel extends ModelWithValidFlagVo { + + @EruptField( + views = @View( + title = "名称" + ), + edit = @Edit( + title = "名称", + type = EditType.INPUT, search = @Search, + notNull = true, + inputType = @InputType + ) + ) + private String name; + + @EruptField( + views = @View( + title = "代号" + ), + edit = @Edit( + title = "代号", + type = EditType.INPUT, search = @Search, + notNull = true, + inputType = @InputType + ) + ) + private String code; + + @EruptField( + views = @View( + title = "详细描述" + ), + edit = @Edit( + title = "详细描述", + type = EditType.INPUT, search = @Search, notNull = true, + inputType = @InputType + ) + ) + private String details; + + @EruptField( + views = @View(title = "类型"), + edit = @Edit( + search = @Search, + title = "获取可选类型", + type = EditType.CHOICE, + desc = "动态获取可选类型", + choiceType = @ChoiceType( + fetchHandler = SqlChoiceFetchHandler.class, + fetchHandlerParams = "select id,name from master_data where category='PRODUCT'" + )) + ) + private String metaType; + + @ManyToOne + @EruptField( + edit = @Edit( + title = "上级树节点", + type = EditType.REFERENCE_TREE, + referenceTreeType = @ReferenceTreeType(pid = "parent.id") + ) + ) + private ProductModuleModel parent; + + + @Column(length = 36, nullable = true, updatable = false) + private String uuid = UUID.randomUUID().toString(); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getDetails() { + return details; + } + + public void setDetails(String details) { + this.details = details; + } + + public String getMetaType() { + return metaType; + } + + public void setMetaType(String metaType) { + this.metaType = metaType; + } + + public ProductModuleModel getParent() { + return parent; + } + + public void setParent(ProductModuleModel parent) { + this.parent = parent; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } +} \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/base/product/model/ProductModuleValidFlagVo.java b/fluent-apps/workspace/src/main/java/io/fluent/base/product/model/ProductModuleValidFlagVo.java new file mode 100644 index 0000000..b267168 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/base/product/model/ProductModuleValidFlagVo.java @@ -0,0 +1,47 @@ +package io.fluent.base.product.model; + +import io.fluent.base.model.ModelWithValidFlagVo; +import lombok.Getter; +import lombok.Setter; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.sub_edit.ReferenceTreeType; +import xyz.erupt.annotation.sub_field.sub_edit.Search; + +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.MappedSuperclass; + +@MappedSuperclass +@Getter +@Setter +public class ProductModuleValidFlagVo extends ModelWithValidFlagVo { + @ManyToOne + @JoinColumn(name = "product_id") + @EruptField( + views = @View(title = "产品名称",column = "details"), + edit = @Edit( + search = @Search, + title = "产品选择", + type = EditType.REFERENCE_TREE, + desc = "动态获取产品", + referenceTreeType = @ReferenceTreeType(id = "id", label = "name", + pid = "parent.id")) + ) + private ProductModuleModel product; + + @ManyToOne + @JoinColumn(name = "module_id") + @EruptField( + views = @View(title = "模块名称",column = "details"), + edit = @Edit(title = "模块选择", search = @Search, type = EditType.REFERENCE_TREE, + referenceTreeType = @ReferenceTreeType(id = "id", label = "name", + dependField = "product", + dependColumn = "parent.id" + )) + ) + private ProductModuleModel module; + +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/base/product/package-info.java b/fluent-apps/workspace/src/main/java/io/fluent/base/product/package-info.java new file mode 100644 index 0000000..15f9d3f --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/base/product/package-info.java @@ -0,0 +1 @@ +package io.fluent.base.product; \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/base/product/repo/ProductModuleRepo.java b/fluent-apps/workspace/src/main/java/io/fluent/base/product/repo/ProductModuleRepo.java new file mode 100644 index 0000000..7898e5f --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/base/product/repo/ProductModuleRepo.java @@ -0,0 +1,18 @@ +package io.fluent.base.product.repo; + + +import io.fluent.base.product.model.ProductModuleModel; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface ProductModuleRepo extends JpaRepository, JpaSpecificationExecutor { + + Optional findProductByNameAndValid(String name, boolean valid); + + Optional findProductByCodeAndValid(String codeName, boolean valid); + Optional findProductByParentIdAndNameAndValid(Long parentId, String name, boolean valid); +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/base/product/service/ProductModuleService.java b/fluent-apps/workspace/src/main/java/io/fluent/base/product/service/ProductModuleService.java new file mode 100644 index 0000000..0c42dac --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/base/product/service/ProductModuleService.java @@ -0,0 +1,57 @@ +package io.fluent.base.product.service; + +import io.fluent.builtin.PingYinUtils; +import io.fluent.base.product.repo.ProductModuleRepo; +import io.fluent.base.proxies.AuditDataEnhancerProxy; +import io.fluent.base.masterdata.repo.MasterDataRepo; +import io.fluent.base.product.model.ProductModuleModel; +import io.fluent.base.masterdata.model.MasterData; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Optional; + +@Service +public class ProductModuleService { + @Resource + private ProductModuleRepo metaRepo; + + @Resource + private MasterDataRepo masterDataRepo; + + @Resource + AuditDataEnhancerProxy dataEnhancerProxy; + + public ProductModuleModel createModuleIfNotExist(Long productId, String moduleName, String updater) { + Optional meta = metaRepo.findProductByParentIdAndNameAndValid(productId, + moduleName, true); + if (meta.isPresent()) return meta.get(); + ProductModuleModel parent = new ProductModuleModel(); + parent.setId(productId); + ProductModuleModel module = new ProductModuleModel(); + module.setName(moduleName); + module.setDetails(moduleName); + module.setParent(parent); + module.setCode(PingYinUtils.convertToPinyinAbbreviation(moduleName)); + MasterData data = masterDataRepo.findMasterDataByCode("MODULE").get(); + module.setMetaType(data.getId().toString()); + dataEnhancerProxy.enhanceTimeAndUserAuditData(module,updater); + return metaRepo.save(module); + } + + public ProductModuleModel findApiServiceProduct() { + String API_SERVICE = "API"; + Optional meta = metaRepo.findProductByCodeAndValid(API_SERVICE, true); + if (meta.isPresent()) return meta.get(); + throw new RuntimeException("Please config API Service as a Product in Product Meta"); + } + + public ProductModuleModel createApiModuleIfNotExist(String moduleName,String updater) { + ProductModuleModel parent = findApiServiceProduct(); + return createModuleIfNotExist(parent.getId(), moduleName,updater); + } + + public ProductModuleModel findByName(String productName) { + return metaRepo.findProductByNameAndValid(productName, true).orElse(null); + } +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/base/project/model/ProjectModel.java b/fluent-apps/workspace/src/main/java/io/fluent/base/project/model/ProjectModel.java new file mode 100644 index 0000000..573eace --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/base/project/model/ProjectModel.java @@ -0,0 +1,89 @@ +package io.fluent.base.project.model; + + +import io.fluent.base.model.ModelWithValidFlagVo; +import io.fluent.base.product.model.ProductModuleModel; +import lombok.Data; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_erupt.Tree; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.sub_edit.InputType; +import xyz.erupt.annotation.sub_field.sub_edit.ReferenceTreeType; +import xyz.erupt.annotation.sub_field.sub_edit.Search; + +import javax.persistence.*; +import java.util.UUID; + +@Erupt(name = "项目", + power = @Power(importable = true, export = true), + tree = @Tree(pid = "parent.id")) +@Entity +@Table(name = "projects") +@Data +public class ProjectModel extends ModelWithValidFlagVo { + + @EruptField( + views = @View( + title = "名称" + ), + edit = @Edit( + title = "名称", + type = EditType.INPUT, search = @Search, + notNull = true, + inputType = @InputType + ) + ) + private String name; + + @EruptField( + views = @View( + title = "代号" + ), + edit = @Edit( + title = "代号", + type = EditType.INPUT, search = @Search, + notNull = true, + inputType = @InputType + ) + ) + private String code; + + @EruptField( + views = @View( + title = "详细描述" + ), + edit = @Edit( + title = "详细描述", + type = EditType.INPUT, search = @Search, notNull = true, + inputType = @InputType + ) + ) + private String details; + + @ManyToOne + @EruptField( + edit = @Edit( + title = "产品列表", + type = EditType.REFERENCE_TREE, + referenceTreeType = @ReferenceTreeType(pid = "parent.id") + ) + ) + private ProductModuleModel productId; + + @ManyToOne + @EruptField( + edit = @Edit( + title = "上级树节点", + type = EditType.REFERENCE_TREE, + referenceTreeType = @ReferenceTreeType(pid = "parent.id") + ) + ) + private ProjectModel parent; + + @Column(length = 36, nullable = false, updatable = false) + private String uuid = UUID.randomUUID().toString(); +} \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/base/project/repo/ProjectModelRepo.java b/fluent-apps/workspace/src/main/java/io/fluent/base/project/repo/ProjectModelRepo.java new file mode 100644 index 0000000..098b228 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/base/project/repo/ProjectModelRepo.java @@ -0,0 +1,18 @@ +package io.fluent.base.project.repo; + + +import io.fluent.base.product.model.ProductModuleModel; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface ProjectModelRepo extends JpaRepository, JpaSpecificationExecutor { + + Optional findProductByNameAndValid(String name, boolean valid); + + Optional findProductByCodeAndValid(String codeName, boolean valid); + Optional findProductByParentIdAndNameAndValid(Long parentId, String name, boolean valid); +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/FluentQAApiModule.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/FluentQAApiModule.java new file mode 100644 index 0000000..2a8570a --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/FluentQAApiModule.java @@ -0,0 +1,125 @@ +package io.fluent.qtm; + + +import io.fluent.qtm.api.model.*; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import xyz.erupt.core.annotation.EruptScan; +import xyz.erupt.core.constant.MenuTypeEnum; +import xyz.erupt.core.module.EruptModule; +import xyz.erupt.core.module.EruptModuleInvoke; +import xyz.erupt.core.module.MetaMenu; +import xyz.erupt.core.module.ModuleInfo; + +import java.util.ArrayList; +import java.util.List; + + +@Configuration +@ComponentScan +@EntityScan +@EruptScan +@EnableConfigurationProperties +public class FluentQAApiModule implements EruptModule { + public FluentQAApiModule() { + } + + @Override + public ModuleInfo info() { + return ModuleInfo.builder().name("fluent-api").build(); + } + + @Override + public void run() { + EruptModule.super.run(); + } + + /** + * API管理: + *

+ * 1. API 仓库管理 + * 2. API 接口定义 + * 3. API 接口录制记录 + * 4. API 接口测试 + * + * @return + */ + @Override + public List initMenus() { + List menus = new ArrayList<>(); + menus.add(MetaMenu.createRootMenu("$APIMgr", "接口管理", "fa fa-exchange", 1)); + + MetaMenu menuForAdded = MetaMenu.createEruptClassMenu(RemoteApi.class, + menus.get(0), 1, MenuTypeEnum.TABLE); + menuForAdded.setIcon("fa fa-scissors"); + menuForAdded.setName("API清单"); + menuForAdded.setCode("$API-List"); + menus.add(menuForAdded); + + MetaMenu rawApiTestCaseMenu = MetaMenu.createEruptClassMenu(RawApiTestCase.class, + menus.get(0), 1, MenuTypeEnum.TABLE); + rawApiTestCaseMenu.setIcon("fa fa-scissors"); + rawApiTestCaseMenu.setName("API生成原始测试用例"); + rawApiTestCaseMenu.setCode("$API-TC-GEN"); + menus.add(rawApiTestCaseMenu); + + MetaMenu apiMonitorRecordMenu = MetaMenu.createEruptClassMenu(ApiMonitorRecord.class, + menus.get(0), 2, MenuTypeEnum.TABLE); + apiMonitorRecordMenu.setIcon("fa fa-repeat"); + apiMonitorRecordMenu.setName("API录制记录"); + apiMonitorRecordMenu.setCode("$API-Record"); + menus.add(apiMonitorRecordMenu); + + MetaMenu apiTestRecord = MetaMenu.createEruptClassMenu( + ApiTestRecord + .class, + menus.get(0), 3, MenuTypeEnum.TABLE); + apiTestRecord.setIcon("fa fa-thumbs-up"); + apiTestRecord.setName("API测试结果记录"); + apiTestRecord.setCode("$API-TestResult"); + menus.add(apiTestRecord); + + MetaMenu apiTestScenarioMenu = MetaMenu.createEruptClassMenu( + ApiTestScenario + .class, + menus.get(0), 4, MenuTypeEnum.TABLE); + apiTestScenarioMenu.setIcon("fa fa-folder"); + apiTestScenarioMenu.setName("API测试场景"); + apiTestScenarioMenu.setCode("$API-TestScenario"); + menus.add(apiTestScenarioMenu); + + MetaMenu apiStepMenu = MetaMenu.createEruptClassMenu( + ApiStep + .class, + menus.get(0), 5, MenuTypeEnum.TABLE); + apiStepMenu.setIcon("fa fa-folder"); + apiStepMenu.setName("API用例步骤"); + apiStepMenu.setCode("$API-Step"); + menus.add(apiStepMenu); +// MetaMenu apiDefMenu = MetaMenu.createSimpleMenu("$API-def", "接口定义", "fa fa-check-square-o", +// menus.get(0), 1, ""); +// menus.add(apiDefMenu); +// addNewMenu( +// menus,"$API-Spec-Git","API定义仓库", "fa fa-meetup", ApiSpecGitRepoModel.class, +// MenuTypeEnum.TABLE,1,0 +// ); +// addNewMenu( +// menus,"$API-Spec","API最新版本", "fa fa-gitlab", ApiSpecVersionModel.class, +// MenuTypeEnum.TABLE,1,1 +// ); + + return menus; + } + + + static { + EruptModuleInvoke.addEruptModule(FluentQAApiModule.class); + } + + @Override + public void initFun() { + EruptModule.super.initFun(); + } +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/FluentUploadTCModule.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/FluentUploadTCModule.java new file mode 100644 index 0000000..70d4748 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/FluentUploadTCModule.java @@ -0,0 +1,53 @@ +package io.fluent.qtm; + +import io.fluent.qtm.upload.model.UploadFileModel; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import xyz.erupt.core.annotation.EruptScan; +import xyz.erupt.core.constant.MenuTypeEnum; +import xyz.erupt.core.module.EruptModule; +import xyz.erupt.core.module.EruptModuleInvoke; +import xyz.erupt.core.module.MetaMenu; +import xyz.erupt.core.module.ModuleInfo; + +import java.util.ArrayList; +import java.util.List; + +@Configuration +@ComponentScan +@EntityScan +@EruptScan +@EnableConfigurationProperties +public class FluentUploadTCModule implements EruptModule { + + public FluentUploadTCModule() { + } + + @Override + public ModuleInfo info() { + return ModuleInfo.builder().name("fluent-tc-sync").build(); + } + + @Override + public void run() { + EruptModule.super.run(); + } + + @Override + public List initMenus() { + List menus = new ArrayList<>(); + menus.add(MetaMenu.createRootMenu("$tc-upload", "测试文件管理", "fa fa-file", 100)); + MetaMenu tfUploadSyncMenu = MetaMenu.createEruptClassMenu(UploadFileModel.class, menus.get(0), 0, MenuTypeEnum.TABLE); + tfUploadSyncMenu.setIcon("fa fa-folder-open"); + tfUploadSyncMenu.setName("测试文件同步"); + tfUploadSyncMenu.setCode("$tc-upload-sync"); + menus.add(tfUploadSyncMenu); + return menus; + } + + static { + EruptModuleInvoke.addEruptModule(FluentUploadTCModule.class); + } +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/handler/GenerateApiCaseByCaptureDataHandler.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/handler/GenerateApiCaseByCaptureDataHandler.java new file mode 100644 index 0000000..1466ab1 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/handler/GenerateApiCaseByCaptureDataHandler.java @@ -0,0 +1,24 @@ +package io.fluent.qtm.api.handler; + +import io.fluent.qtm.api.model.ApiMonitorRecord; +import io.fluent.qtm.api.service.ApiTestCaseService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import xyz.erupt.annotation.fun.OperationHandler; + +import javax.annotation.Resource; +import java.util.List; + +@Service +@Slf4j +public class GenerateApiCaseByCaptureDataHandler implements OperationHandler { + + @Resource + private ApiTestCaseService apiService; + @Override + public String exec(List data, Void unused, String[] param) { + log.info("start convert api capture data"); + apiService.convertApiMonitorRecordToTestCase(data); + return null; + } +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/handler/GenerateApiTestStepByApiTestRecord.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/handler/GenerateApiTestStepByApiTestRecord.java new file mode 100644 index 0000000..02361bd --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/handler/GenerateApiTestStepByApiTestRecord.java @@ -0,0 +1,24 @@ +package io.fluent.qtm.api.handler; + +import io.fluent.qtm.api.model.ApiTestRecord; +import io.fluent.qtm.api.service.ApiTestCaseService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import xyz.erupt.annotation.fun.OperationHandler; + +import javax.annotation.Resource; +import java.util.List; + +@Service +@Slf4j +public class GenerateApiTestStepByApiTestRecord implements OperationHandler { + + @Resource + private ApiTestCaseService apiService; + @Override + public String exec(List data, Void unused, String[] param) { + log.info("start convert api capture data"); + apiService.convertApiTestResultToApiTestStep(data); + return null; + } +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/handler/GenerateRawApiCaseHandler.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/handler/GenerateRawApiCaseHandler.java new file mode 100644 index 0000000..bd98597 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/handler/GenerateRawApiCaseHandler.java @@ -0,0 +1,22 @@ +package io.fluent.qtm.api.handler; + +import io.fluent.qtm.api.model.RemoteApi; +import io.fluent.qtm.api.service.ApiTestCaseService; +import org.springframework.stereotype.Service; +import xyz.erupt.annotation.fun.OperationHandler; + +import javax.annotation.Resource; +import java.util.List; + +@Service +public class GenerateRawApiCaseHandler implements OperationHandler { + + @Resource + private ApiTestCaseService apiService; + @Override + public String exec(List data, Void unused, String[] param) { + System.out.println("this is tests"); + apiService.convertToRawTestCase(data); + return null; + } +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiMonitorRecord.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiMonitorRecord.java new file mode 100644 index 0000000..cc2999e --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiMonitorRecord.java @@ -0,0 +1,131 @@ +package io.fluent.qtm.api.model; + + +import io.fluent.qtm.api.handler.GenerateApiCaseByCaptureDataHandler; +import io.fluent.base.handlers.SqlTagFetchHandler; +import lombok.Data; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_erupt.Layout; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_erupt.RowOperation; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.ViewType; +import xyz.erupt.annotation.sub_field.sub_edit.CodeEditorType; +import xyz.erupt.annotation.sub_field.sub_edit.Search; +import xyz.erupt.annotation.sub_field.sub_edit.TagsType; +import xyz.erupt.jpa.model.MetaModel; + +import javax.persistence.Entity; +import javax.persistence.Table; + +@DynamicUpdate +@DynamicInsert +@Entity +@Table(name = "api_monitor_record") +@Erupt( + name = "接口访问记录", + layout = @Layout( + tableLeftFixed = 3, + pageSize = 30), + power = @Power(importable = true, export = true), + rowOperation = {@RowOperation( + title = "生成接口用例数据", + operationHandler = GenerateApiCaseByCaptureDataHandler.class)}, + orderBy = "ApiMonitorRecord.id desc" + +) +@Data +public class ApiMonitorRecord extends MetaModel { + + @EruptField( + views = @View(title = "app"), + edit = @Edit( + title = "app应用名", + type = EditType.TAGS, search = @Search(vague = true), notNull = true, + tagsType = @TagsType( + fetchHandler = SqlTagFetchHandler.class, + fetchHandlerParams = "select distinct app from api_monitor_record" + ) + )) + private String app; + @EruptField( + views = @View(title = "录制名称"), + edit = @Edit(title = "录制名称", notNull = true, search = @Search) + ) + private String recordName; + @EruptField( + views = @View(title = "请求地址"), + edit = @Edit(title = "请求地址", notNull = true, search = @Search) + ) + private String requestUrl; + + @EruptField( + views = @View(title = "服务"), + edit = @Edit( + title = "服务", + type = EditType.TAGS, search = @Search(vague = true), notNull = true, + tagsType = @TagsType( + fetchHandler = SqlTagFetchHandler.class, + fetchHandlerParams = "select distinct service from api_monitor_record" + ) + ) + ) + + private String service; + @EruptField( + views = @View(title = "接口名称"), + edit = @Edit(title = "接口名称", notNull = true, search = @Search) + ) + private String api; + + @EruptField( + views = @View(title = "服务URL"), + edit = @Edit(title = "服务URL", notNull = true, search = @Search) + ) + private String path; + + @EruptField( + views = @View(title = "请求头"), + edit = @Edit(title = "请求报文", type = EditType.CODE_EDITOR, codeEditType = @CodeEditorType(language = "json")) + ) + private String requestHeaders; + + @EruptField( + views = @View(title = "HTTP方法"), + edit = @Edit(title = "HTTP方法", notNull = true, search = @Search) + ) + private String method; + + @EruptField( + views = @View(title = "请求报文", type = ViewType.CODE), + edit = @Edit(title = "请求报文", type = EditType.CODE_EDITOR, codeEditType = @CodeEditorType(language = "json")) + ) + private String requestBody; + + + @EruptField( + views = @View(title = "response_headers"), + edit = @Edit(title = "responseHeaders", type = EditType.CODE_EDITOR, codeEditType = @CodeEditorType(language = "json")) + ) + private String responseHeaders; + + @EruptField( + views = @View(title = "status_code"), + edit = @Edit(title = "status_code", notNull = true, search = @Search) + ) + private int statusCode; + + @EruptField( + views = @View(title = "返回报文", type = ViewType.CODE), + edit = @Edit(title = "返回报文", type = EditType.CODE_EDITOR, codeEditType = @CodeEditorType(language = "json")) + ) + private String responseBody; + + + +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiSpecChangeModel.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiSpecChangeModel.java new file mode 100644 index 0000000..723930d --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiSpecChangeModel.java @@ -0,0 +1,52 @@ +package io.fluent.qtm.api.model; + +import lombok.Data; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_erupt.Layout; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.jpa.model.BaseModel; + +import javax.persistence.Entity; +import javax.persistence.Table; +import java.time.LocalDateTime; + +@DynamicUpdate +@DynamicInsert +@Entity +@Table(name = "api_spec_change") +@Erupt( + layout = @Layout( + tableLeftFixed = 3, + pageSize = 30), + name = "api spec 变化记录", power = @Power(export = true) +) +@Data +public class ApiSpecChangeModel extends BaseModel { + @EruptField( + views = @View(title = "应用名-appName") + ) + private String name; + @EruptField( + views = @View(title = "GIT URL") + ) + private String gitUrl; + @EruptField( + views = @View(title = "GIT分支") + ) + private String branch; + + @EruptField( + views = @View(title = "创建时间") + ) + private LocalDateTime createdTime; + + @EruptField( + views = @View(title = "appVersion") + ) + private String appVersion; + +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiSpecGitRepoModel.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiSpecGitRepoModel.java new file mode 100644 index 0000000..cb97dfd --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiSpecGitRepoModel.java @@ -0,0 +1,47 @@ +package io.fluent.qtm.api.model; + +import lombok.Data; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_erupt.Layout; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.sub_edit.Search; +import xyz.erupt.jpa.model.MetaModel; + +import javax.persistence.Entity; +import javax.persistence.Table; + +@Entity +@Table(name = "apispec_git_repo") +@Data +@Erupt(name = "skel仓库设置", layout = @Layout( + tableLeftFixed = 3, + pageSize = 30), + power = @Power(importable = true, export = true)) +public class ApiSpecGitRepoModel extends MetaModel { + @EruptField( + views = @View(title = "应用名-appName"), + edit = @Edit(title = "应用名-App Name", notNull = true, search = @Search) + ) + private String name; + @EruptField( + views = @View(title = "gitUrl"), + edit = @Edit(title = "gitUrl", notNull = true) + ) + private String gitUrl; + + @EruptField( + views = @View(title = "gitlabId"), + edit = @Edit(title = "gitlabId", notNull = true) + ) + private Integer gitlabId; + + @EruptField( + views = @View(title = "webUrl"), + edit = @Edit(title = "webUrl", notNull = true) + ) + private String webUrl; + +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiSpecVersionModel.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiSpecVersionModel.java new file mode 100644 index 0000000..6bd226d --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiSpecVersionModel.java @@ -0,0 +1,102 @@ +package io.fluent.qtm.api.model; + +import io.fluent.base.model.ModelWithValidFlagVo; +import lombok.Data; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_erupt.Layout; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.ViewType; +import xyz.erupt.annotation.sub_field.sub_edit.CodeEditorType; +import xyz.erupt.annotation.sub_field.sub_edit.InputType; +import xyz.erupt.annotation.sub_field.sub_edit.Search; + +import javax.persistence.Entity; +import javax.persistence.Table; + +@DynamicUpdate +@DynamicInsert +@Entity +@Table(name = "api_spec_version") +@Erupt( + name = "远程服务原始文件", + power = @Power(export = true), + layout = @Layout( + tableLeftFixed = 3, + pageSize = 30) +) +@Data +@SQLDelete(sql = "update api_spec_version set valid=false where id=?") +@Where(clause = "valid = true") +public class ApiSpecVersionModel extends ModelWithValidFlagVo { + @EruptField( + views = @View( + title = "名称" + ), + edit = @Edit( + title = "名称", + type = EditType.INPUT, search = @Search, notNull = true, + inputType = @InputType + ) + ) + private String name; + + + @EruptField( + views = @View( + title = "名称" + ), + edit = @Edit( + title = "名称", + type = EditType.INPUT, search = @Search, notNull = true, + inputType = @InputType + ) + ) + private String type="POSTMAN"; + + @EruptField( + views = @View( + title = "服务类型" + ), + edit = @Edit( + title = "服务类型", + type = EditType.INPUT, search = @Search, notNull = true, + inputType = @InputType + ) + ) + private String serviceType; //API or RPC + + @EruptField( + views = @View( + title = "版本" + ), + edit = @Edit( + title = "版本", + type = EditType.INPUT, search = @Search, notNull = true, + inputType = @InputType + ) + ) + private String appVersion; + + @EruptField( + views = @View(title = "GIT URL") + ) + private String gitUrl; + @EruptField( + views = @View(title = "GIT分支") + ) + private String branch; + + @EruptField( + views = @View(title = "接口定义", type = ViewType.CODE), + edit = @Edit(title = "接口定义", type = EditType.CODE_EDITOR, codeEditType = @CodeEditorType(language = "json")) + ) + private String spec; +} \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiStep.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiStep.java new file mode 100644 index 0000000..9f26690 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiStep.java @@ -0,0 +1,156 @@ +package io.fluent.qtm.api.model; + +import io.fluent.base.handlers.SqlTagFetchHandler; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_erupt.Layout; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.sub_edit.CodeEditorType; +import xyz.erupt.annotation.sub_field.sub_edit.Search; +import xyz.erupt.annotation.sub_field.sub_edit.TagsType; +import xyz.erupt.jpa.model.MetaModel; + +import javax.persistence.Entity; +import javax.persistence.Table; + +@DynamicUpdate +@DynamicInsert +@Entity +@Table(name = "api_steps") +@Erupt( + name = "接口测试用例", layout = @Layout( + tableLeftFixed = 3, + pageSize = 30), power = @Power(importable = true, export = true), + orderBy = "ApiTestStep.updateTime desc" +) +public class ApiStep extends MetaModel{ + + @EruptField( + views = @View(title = "场景"), + edit = @Edit(title = "场景", notNull = true, search = @Search) + ) + private String scenario; + + @EruptField( + views = @View(title = "用例名称"), + edit = @Edit(title = "用例名称", notNull = true, search = @Search) + ) + private String caseName; + + @EruptField( + views = @View(title = "服务"), + edit = @Edit( + search = @Search, + title = "获取可选服务", + type = EditType.TAGS, + desc = "获取可选服务", + tagsType = @TagsType( + fetchHandler = SqlTagFetchHandler.class, + fetchHandlerParams = "select distinct service_name from remote_services where type='API' and valid=true" + )) + ) + private String serviceName; + @EruptField( + views = @View(title = "服务方法"), + edit = @Edit(title = "服务方法", notNull = true, search = @Search) + ) + private String serviceMethod; + + @EruptField( + views = @View(title = "接口路径"), + edit = @Edit(title = "接口路径", notNull = true, search = @Search) + ) + private String path; + + @EruptField( +// views = @View(title = "测试请求", type = ViewType.CODE), + edit = @Edit(title = "测试请求", type = EditType.CODE_EDITOR, codeEditType = @CodeEditorType(language = "json")) + ) + private String request; + @EruptField( +// views = @View(title = "接口请求结果"), + edit = @Edit(title = "接口请求结果", + type = EditType.CODE_EDITOR, codeEditType = @CodeEditorType(language = "json")) + ) + private String result; + + + @EruptField( +// views = @View(title = "预期结果"), + edit = @Edit(title = "预期结果", notNull = true, type = EditType.CODE_EDITOR, + codeEditType = @CodeEditorType(language = "json")) + ) + private String expect; + + + public String getScenario() { + return scenario; + } + + public void setScenario(String scenario) { + this.scenario = scenario; + } + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public String getServiceMethod() { + return serviceMethod; + } + + public void setServiceMethod(String serviceMethod) { + this.serviceMethod = serviceMethod; + } + + public String getCaseName() { + return caseName; + } + + public void setCaseName(String caseName) { + this.caseName = caseName; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getRequest() { + return request; + } + + public void setRequest(String request) { + this.request = request; + } + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } + + + + public String getExpect() { + return expect; + } + + public void setExpect(String expect) { + this.expect = expect; + } +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiTestRecord.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiTestRecord.java new file mode 100644 index 0000000..e03248c --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiTestRecord.java @@ -0,0 +1,131 @@ +package io.fluent.qtm.api.model; + +import io.fluent.qtm.api.handler.GenerateApiTestStepByApiTestRecord; +import io.fluent.base.handlers.SqlTagFetchHandler; +import lombok.Data; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_erupt.Layout; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_erupt.RowOperation; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.sub_edit.CodeEditorType; +import xyz.erupt.annotation.sub_field.sub_edit.Search; +import xyz.erupt.annotation.sub_field.sub_edit.TagsType; +import xyz.erupt.jpa.model.MetaModel; + +import javax.persistence.Entity; +import javax.persistence.Table; + +/** + * 1. 原先的表结构设计几个问题: + * - 没有办法区分那次测试运行记录 + * - 查找不太方便 + * - name 和service name 重复,没有必要同时使用 + * - serviceName 从remote service里面取不过滤API,不够精确 + * 修改方式: + * - name 修改为测试用例运行名称 + * - serviceName 取tags 从remote service 的API 中取 + */ +@DynamicUpdate +@DynamicInsert +@Entity +@Table(name = "api_test_record") +@Erupt( + name = "接口测试结果", layout = @Layout( + tableLeftFixed = 3, + pageSize = 30), power = @Power(importable = true, export = true), + orderBy = "ApiTestRecord.id desc", + rowOperation = {@RowOperation( + title = "生成可用测试步骤", + operationHandler = GenerateApiTestStepByApiTestRecord.class)} +) +@Data +public class ApiTestRecord extends MetaModel { + @EruptField( + views = @View(title = "测试运行名称"), + edit = @Edit(title = "name", search = @Search) + ) + private String name; + + @EruptField( + views = @View(title = "场景"), + edit = @Edit(title = "场景", notNull = true, search = @Search) + ) + private String scenario; + + @EruptField( + views = @View(title = "用例名称"), + edit = @Edit(title = "用例名称", notNull = true, search = @Search) + ) + private String caseName; + + @EruptField( + views = @View(title = "服务"), + edit = @Edit( + search = @Search, + title = "获取可选服务", + type = EditType.TAGS, + desc = "获取可选服务", + tagsType = @TagsType( + fetchHandler = SqlTagFetchHandler.class, + fetchHandlerParams = "select distinct service_name from remote_services where type='API' and valid=true" + )) + ) + private String serviceName; + @EruptField( + views = @View(title = "服务方法"), + edit = @Edit(title = "服务方法", notNull = true, search = @Search) + ) + private String serviceMethod; + + @EruptField( + views = @View(title = "接口路径"), + edit = @Edit(title = "接口路径", notNull = true, search = @Search) + ) + private String path; + + @EruptField( +// views = @View(title = "测试请求", type = ViewType.CODE), + edit = @Edit(title = "测试请求", type = EditType.CODE_EDITOR, codeEditType = @CodeEditorType(language = "json")) + ) + private String request; + @EruptField( +// views = @View(title = "接口请求结果"), + edit = @Edit(title = "接口请求结果", + type = EditType.CODE_EDITOR, codeEditType = @CodeEditorType(language = "json")) + ) + private String result; + + @EruptField( + views = @View(title = "状态码"), + edit = @Edit(title = "状态码", notNull = true, search = @Search) + ) + private String statusCode; + + @EruptField( + views = @View(title = "错误日志"), + edit = @Edit(title = "错误日志", + type = EditType.CODE_EDITOR, codeEditType = @CodeEditorType(language = "json")) + ) + private String errorLog; + + @EruptField( +// views = @View(title = "预期结果"), + edit = @Edit(title = "预期结果", notNull = true, type = EditType.CODE_EDITOR, + codeEditType = @CodeEditorType(language = "json")) + ) + private String expect; + + //TODO: 通过或者失败 + @EruptField( + views = @View(title = "用例执行结果"), + edit = @Edit(title = "用例执行结果", search = @Search) + ) + private boolean isSuccess; + +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiTestScenario.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiTestScenario.java new file mode 100644 index 0000000..eb187f8 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/ApiTestScenario.java @@ -0,0 +1,157 @@ +package io.fluent.qtm.api.model; + +import io.fluent.base.handlers.SqlTagFetchHandler; +import io.fluent.base.model.ModelWithValidFlag; +import io.fluent.base.product.model.ProductModuleModel; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_erupt.Layout; +import xyz.erupt.annotation.sub_erupt.LinkTree; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.sub_edit.CodeEditorType; +import xyz.erupt.annotation.sub_field.sub_edit.ReferenceTreeType; +import xyz.erupt.annotation.sub_field.sub_edit.Search; +import xyz.erupt.annotation.sub_field.sub_edit.TagsType; + +import javax.persistence.*; +import java.util.Set; + +/** + * + */ +@Entity +@Erupt(name = "接口测试用例", + power = @Power(export = true), + orderBy = "ApiTestScenario.updateTime desc", + linkTree = @LinkTree(field = "module"), + layout = @Layout( + tableLeftFixed = 3, + pageSize = 30)) +@Table(name = "api_test_scenario") +public class ApiTestScenario extends ModelWithValidFlag { + + @ManyToOne + @JoinColumn(name = "product_id") + @EruptField( + views = @View(title = "所属模块", column = "details"), + edit = @Edit( + notNull = true, + search = @Search, + title = "产品模块选择", + type = EditType.REFERENCE_TREE, + desc = "动态获取产品", + referenceTreeType = @ReferenceTreeType(id = "id", label = "name", + pid = "parent.id")) + ) + private ProductModuleModel module; + + + @EruptField( + views = @View( + title = "测试场景" + ), + edit = @Edit( + title = "测试场景", + type = EditType.INPUT, search = @Search, notNull = true + ) + ) + private String testScenario; + + @EruptField( + views = @View( + title = "测试场景详细描述" + ), + edit = @Edit( + title = "测试场景详细描述", + type = EditType.TEXTAREA, search = @Search, notNull = true + ) + ) + private String details; + + @EruptField( + views = @View( + title = "优先级" + ), + edit = @Edit( + title = "优先级", + type = EditType.TAGS, + search = @Search, + tagsType = @TagsType( + fetchHandler = SqlTagFetchHandler.class, + fetchHandlerParams = "select distinct key,detail from master_data where category_code = 'PRIORITY' order by 1 " + ) + ) + ) + private String priority = "P2"; + + @EruptField( + views = @View(title = "场景参数"), + edit = @Edit(title = "场景参数", + type = EditType.CODE_EDITOR, codeEditType = @CodeEditorType(language = "json")) + ) + private String scenarioParameters; + + @JoinTable(name = "api_test_scenario_steps", + joinColumns = @JoinColumn(name = "api_test_scenario_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "api_test_step_id", referencedColumnName = "id")) + @ManyToMany(fetch = FetchType.EAGER) + @EruptField( + views = @View(title = "包含用例"), + edit = @Edit( + title = "包含用例", + type = EditType.TAB_TABLE_REFER + ) + ) + private Set testSteps; + public String getPriority() { + return priority; + } + + public void setPriority(String priority) { + this.priority = priority; + } + + + public ProductModuleModel getModule() { + return module; + } + + public void setModule(ProductModuleModel module) { + this.module = module; + } + + public String getTestScenario() { + return testScenario; + } + + public void setTestScenario(String testScenario) { + this.testScenario = testScenario; + } + + public String getDetails() { + return details; + } + + public void setDetails(String details) { + this.details = details; + } + + public String getScenarioParameters() { + return scenarioParameters; + } + + public void setScenarioParameters(String scenarioParameters) { + this.scenarioParameters = scenarioParameters; + } + + public Set getTestSteps() { + return testSteps; + } + + public void setTestSteps(Set testSteps) { + this.testSteps = testSteps; + } +} \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/RawApiTestCase.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/RawApiTestCase.java new file mode 100644 index 0000000..9498f09 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/RawApiTestCase.java @@ -0,0 +1,96 @@ +package io.fluent.qtm.api.model; + +import lombok.Data; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_erupt.Layout; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.ViewType; +import xyz.erupt.annotation.sub_field.sub_edit.CodeEditorType; +import xyz.erupt.annotation.sub_field.sub_edit.Search; +import xyz.erupt.jpa.model.MetaModel; + +import javax.persistence.Entity; +import javax.persistence.Table; + + +@DynamicUpdate +@DynamicInsert +@Entity +@Table(name = "raw_api_cases") +@Erupt( + name = "接口测试用例生成", layout = @Layout( + tableLeftFixed = 3, + pageSize = 30), power = @Power(importable = true, export = true), + orderBy = "RawApiTestCase.createTime " +) +@Data +public class RawApiTestCase extends MetaModel{ + @EruptField( + views = @View(title = "测试场景"), + edit = @Edit(title = "测试场景", search = @Search) + ) + private String scenario; + + @EruptField( + views = @View(title = "服务名称"), + edit = @Edit(title = "服务名称", notNull = true, search = @Search) + ) + private String serviceName; + + @EruptField( + views = @View(title = "API接口"), + edit = @Edit(title = "API接口", notNull = true, search = @Search) + ) + private String serviceMethod; + + @EruptField( + views = @View(title = "用例名称"), + edit = @Edit(title = "用例名称", notNull = true, search = @Search) + ) + private String name; + + @EruptField( + views = @View(title = "请求路径"), + edit = @Edit(title = "请求路径", notNull = true, search = @Search) + ) + private String uri; + + @EruptField( + views = @View(title = "请求方法"), + edit = @Edit(title = "请求方法", notNull = true) + ) + private String method = "POST"; + + @EruptField( + views = @View(title = "输入", type = ViewType.CODE), + edit = @Edit(title = "输入", + type = EditType.CODE_EDITOR, codeEditType = @CodeEditorType(language = "json")) + ) + private String input; + + @EruptField( + views = @View(title = "期望结果", type = ViewType.CODE), + edit = @Edit(title = "期望结果", type = EditType.CODE_EDITOR, + codeEditType = @CodeEditorType(language = "json")) + ) + private String expected; + + @EruptField( + views = @View(title = "优先级"), + edit = @Edit(title = "优先级") + ) + private String priority = "P1"; + + @EruptField( + views = @View(title = "是否运行"), + edit = @Edit(title = "是否运行") + ) + private boolean isRun = true; + +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/RemoteApi.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/RemoteApi.java new file mode 100644 index 0000000..84763bd --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/RemoteApi.java @@ -0,0 +1,275 @@ +package io.fluent.qtm.api.model; + +import cn.hutool.core.lang.UUID; +import io.fluent.qtm.api.handler.GenerateRawApiCaseHandler; +import io.fluent.base.handlers.SqlTagFetchHandler; +import io.fluent.base.model.ModelWithValidFlag; +import lombok.Data; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_erupt.Layout; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_erupt.RowOperation; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.ViewType; +import xyz.erupt.annotation.sub_field.sub_edit.*; +import xyz.erupt.toolkit.handler.SqlChoiceFetchHandler; + +import javax.persistence.Entity; +import javax.persistence.Table; + +@DynamicUpdate +@DynamicInsert +@Entity +@Table(name = "remote_services") +@Erupt( + name = "远程服务清单", layout = @Layout( + tableLeftFixed = 3, + pageSize = 30), + power = @Power(export = true), + rowOperation = {@RowOperation( + title = "生成原始接口用例", + operationHandler = GenerateRawApiCaseHandler.class)} +) +@Data +@SQLDelete(sql = "update remote_services set valid=false where id=?") +@Where(clause = "valid = true") +public class RemoteApi extends ModelWithValidFlag { + @EruptField( + views = @View( + title = "名称" + ), + edit = @Edit( + title = "名称", + type = EditType.INPUT, search = @Search, notNull = true, + inputType = @InputType + ) + ) + private String name; + + @EruptField( + views = @View( + title = "产品" + ), + edit = @Edit( + title = "产品", + type = EditType.CHOICE, + desc = "获取产品", + choiceType = @ChoiceType( + fetchHandler = SqlChoiceFetchHandler.class, + fetchHandlerParams = "select id,name,details from products where valid =true and parent_id is NULL" + )) + ) + private Long productId; + + @EruptField( + views = @View(title = "模块名"), + edit = @Edit( + search = @Search, + title = "获取可选模块", + type = EditType.TAGS, + desc = "动态获取可选模块", + tagsType = @TagsType( + fetchHandler = SqlTagFetchHandler.class, + fetchHandlerParams = "select distinct module_name from remote_services where valid=true" + )) + ) + private String moduleName; + + @EruptField( + views = @View(title = "服务"), + edit = @Edit( + search = @Search, + title = "获取可选服务", + type = EditType.TAGS, + desc = "获取可选服务", + tagsType = @TagsType( + fetchHandler = SqlTagFetchHandler.class, + fetchHandlerParams = "select distinct service_name from remote_services where valid=true" + )) + ) + private String serviceName; + + @EruptField( + views = @View(title = "地址"), + edit = @Edit(title = "地址", notNull = true) + ) + private String endpoint; + + @EruptField( + views = @View(title = "方法"), + edit = @Edit(title = "方法", notNull = true, search = @Search) + ) + private String serviceMethod; + + @EruptField( + views = @View(title = "http请求方法"), + edit = @Edit(title = "http请求方法", notNull = true) + ) + private String httpMethod; + + @EruptField( + views = @View(title = "请求报文", type = ViewType.CODE), + edit = @Edit(title = "请求报文", type = EditType.CODE_EDITOR, codeEditType = @CodeEditorType(language = "json")) + ) + private String body; + + @EruptField( + views = @View(title = "接口类型"), + edit = @Edit(title = "接口类型", search = @Search, + type = EditType.CHOICE, choiceType = @ChoiceType( + vl = {@VL(value = "API", label = "API"), @VL(value = "RPC", label = "RPC")} + )) + ) + private String type; + + @EruptField( + views = @View(title = "服务使用状态"), + edit = @Edit(title = "服务使用状态", + search = @Search, notNull = true, + type = EditType.CHOICE, choiceType = @ChoiceType( + vl = {@VL(value = "NEW", label = "新增"), + @VL(value = "IN_USE", label = "使用中"), + @VL(value = "UPDATE", label = "更新"), + @VL(value = "END_OF_LIFE", label = "已作废"),}))) + private String status; + + @EruptField( + views = @View( + title = "引入时版本" + ), + edit = @Edit( + title = "引入时版本", + type = EditType.INPUT, search = @Search, notNull = true, + inputType = @InputType + ) + ) + private String addedVersion; + + @EruptField( + views = @View( + title = "最新版本" + ), + edit = @Edit( + title = "最新版本", + type = EditType.INPUT, search = @Search, notNull = true, + inputType = @InputType + ) + ) + private String latestVersion; + + @EruptField( + views = @View(show = false, title = "uid") + ) + private String uId = UUID.fastUUID().toString(); + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Long getProductId() { + return productId; + } + + public void setProductId(Long productId) { + this.productId = productId; + } + + public String getModuleName() { + return moduleName; + } + + public void setModuleName(String moduleName) { + this.moduleName = moduleName; + } + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public String getEndpoint() { + return endpoint; + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + + public String getServiceMethod() { + return serviceMethod; + } + + public void setServiceMethod(String serviceMethod) { + this.serviceMethod = serviceMethod; + } + + public String getHttpMethod() { + return httpMethod; + } + + public void setHttpMethod(String httpMethod) { + this.httpMethod = httpMethod; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getAddedVersion() { + return addedVersion; + } + + public void setAddedVersion(String addedVersion) { + this.addedVersion = addedVersion; + } + + public String getLatestVersion() { + return latestVersion; + } + + public void setLatestVersion(String latestVersion) { + this.latestVersion = latestVersion; + } + + public String getuId() { + return uId; + } + + public void setuId(String uId) { + this.uId = uId; + } +} \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/RemoteApiStatus.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/RemoteApiStatus.java new file mode 100644 index 0000000..4b66a5c --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/RemoteApiStatus.java @@ -0,0 +1,5 @@ +package io.fluent.qtm.api.model; + +public enum RemoteApiStatus { + NEW,IN_USE,UPDATED,END_OF_LIFE +} \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/RemoteApiType.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/RemoteApiType.java new file mode 100644 index 0000000..74c2557 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/model/RemoteApiType.java @@ -0,0 +1,5 @@ +package io.fluent.qtm.api.model; + +public enum RemoteApiType { + API,RPC +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/package-info.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/package-info.java new file mode 100644 index 0000000..73f4e8e --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/package-info.java @@ -0,0 +1 @@ +package io.fluent.qtm.api; \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/ApiMonitorRecordRepo.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/ApiMonitorRecordRepo.java new file mode 100644 index 0000000..e03552b --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/ApiMonitorRecordRepo.java @@ -0,0 +1,14 @@ +package io.fluent.qtm.api.repo; + +import io.fluent.qtm.api.model.ApiMonitorRecord; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface ApiMonitorRecordRepo extends JpaRepository, JpaSpecificationExecutor { + + List findApiMonitorRecordByPath(String path); +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/ApiSpecChangeRepository.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/ApiSpecChangeRepository.java new file mode 100644 index 0000000..ff3cdf3 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/ApiSpecChangeRepository.java @@ -0,0 +1,11 @@ +package io.fluent.qtm.api.repo; + + +import io.fluent.qtm.api.model.ApiSpecChangeModel; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ApiSpecChangeRepository extends JpaRepository { + +} \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/ApiSpecGitRepoRepository.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/ApiSpecGitRepoRepository.java new file mode 100644 index 0000000..4a6af7a --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/ApiSpecGitRepoRepository.java @@ -0,0 +1,10 @@ +package io.fluent.qtm.api.repo; + +import io.fluent.qtm.api.model.ApiSpecGitRepoModel; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ApiSpecGitRepoRepository extends JpaRepository { + +} \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/ApiSpecVersionRepository.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/ApiSpecVersionRepository.java new file mode 100644 index 0000000..361f79d --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/ApiSpecVersionRepository.java @@ -0,0 +1,10 @@ +package io.fluent.qtm.api.repo; + +import io.fluent.qtm.api.model.ApiSpecVersionModel; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ApiSpecVersionRepository extends JpaRepository { + +} \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/ApiTestScenarioRepo.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/ApiTestScenarioRepo.java new file mode 100644 index 0000000..e389772 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/ApiTestScenarioRepo.java @@ -0,0 +1,10 @@ +package io.fluent.qtm.api.repo; + +import io.fluent.qtm.api.model.ApiTestScenario; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.stereotype.Repository; + +@Repository +public interface ApiTestScenarioRepo extends JpaRepository, JpaSpecificationExecutor { +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/ApiTestStepRepo.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/ApiTestStepRepo.java new file mode 100644 index 0000000..f867291 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/ApiTestStepRepo.java @@ -0,0 +1,10 @@ +package io.fluent.qtm.api.repo; + +import io.fluent.qtm.api.model.ApiStep; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.stereotype.Repository; + +@Repository +public interface ApiTestStepRepo extends JpaRepository, JpaSpecificationExecutor { +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/RawApiTestCaseRepo.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/RawApiTestCaseRepo.java new file mode 100644 index 0000000..fb9e408 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/RawApiTestCaseRepo.java @@ -0,0 +1,10 @@ +package io.fluent.qtm.api.repo; + +import io.fluent.qtm.api.model.RawApiTestCase; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.stereotype.Repository; + +@Repository +public interface RawApiTestCaseRepo extends JpaRepository, JpaSpecificationExecutor { +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/RemoteServiceRepo.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/RemoteServiceRepo.java new file mode 100644 index 0000000..f6f4ad0 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/repo/RemoteServiceRepo.java @@ -0,0 +1,23 @@ +package io.fluent.qtm.api.repo; + +import io.fluent.qtm.api.model.RemoteApi; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; + +@Repository +public interface RemoteServiceRepo extends JpaRepository, JpaSpecificationExecutor { + + Optional findRemoteApiByEndpointAndServiceNameAndServiceMethod( + String endpoint,String serviceName,String serviceMethod + ); + + Optional> findRemoteApiByModuleNameAndServiceNameAndLatestVersionNot( + String moduleName,String serviceName,String latestVersion + ); + + +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/service/ApiTestCaseService.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/service/ApiTestCaseService.java new file mode 100644 index 0000000..cd465be --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/service/ApiTestCaseService.java @@ -0,0 +1,107 @@ +package io.fluent.qtm.api.service; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import io.fluent.builtin.CollectionsUtils; +import io.fluent.qtm.api.model.*; +import io.fluent.qtm.api.repo.ApiMonitorRecordRepo; +import io.fluent.qtm.api.repo.ApiTestStepRepo; +import io.fluent.qtm.api.repo.RawApiTestCaseRepo; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +@Service +public class ApiTestCaseService { + private final String DEFAULT_EXPECTED = "{ \"status_code\":200,\"values\":{}\n" + + "}"; + @Resource + RawApiTestCaseRepo rawApiTestCaseRepo; + + @Resource + ApiMonitorRecordRepo apiMonitorRecordRepo; + + @Resource + ApiTestStepRepo apiTestStepRepo; + + + /** + * @param services: HTTP API Services + * 1. Merge All HttpAPI Services if method,service and request-body/input is same + */ + public void convertToRawTestCase(List services) { + List cases = new ArrayList<>(); + services.forEach(service -> { + RawApiTestCase apiCase = new RawApiTestCase(); + BeanUtils.copyProperties(service, apiCase); + apiCase.setUri(service.getEndpoint()); + apiCase.setExpected(DEFAULT_EXPECTED); + //get body + String path = service.getEndpoint().replaceAll("https://\\{\\{base_url\\}\\}", ""); + List result = apiMonitorRecordRepo.findApiMonitorRecordByPath(path); + if (!result.isEmpty()) { + apiCase.setInput(result.get(0).getRequestBody()); + } else { + apiCase.setInput(service.getBody()); + } + cases.add(apiCase); + }); + rawApiTestCaseRepo.saveAll(cases); + } + + /** + * @param records Http traffic + * 1. Merge All HttpAPI Services if method,service and request-body/input is same + */ + public void convertApiMonitorRecordToTestCase(List records) { + List cases = new ArrayList<>(); + List result = CollectionsUtils.filterToReduceRedundant( + records, new Function() { + @Override + public String apply(ApiMonitorRecord apiMonitorRecord) { + return StrUtil.join( + "-", apiMonitorRecord.getApi(), apiMonitorRecord.getApp(), + apiMonitorRecord.getService(), apiMonitorRecord.getPath(), + apiMonitorRecord.getMethod(), apiMonitorRecord.getRequestBody() + ); + } + } + ); + result.forEach(service -> { + RawApiTestCase apiCase = new RawApiTestCase(); + BeanUtils.copyProperties(service, apiCase); + apiCase.setUri(service.getPath()); + apiCase.setExpected(DEFAULT_EXPECTED); + apiCase.setServiceMethod(service.getMethod()); + apiCase.setServiceName(service.getService()); + apiCase.setName(service.getService()); + apiCase.setServiceMethod(service.getApi()); + //get body + apiCase.setInput(service.getRequestBody()); + apiCase.setScenario(service.getRecordName()); + cases.add(apiCase); + }); + rawApiTestCaseRepo.saveAll(cases); + } + + /** + * Only Passed Test Scenario could be converted into test steps + * + * @param data + */ + public void convertApiTestResultToApiTestStep(List data) { + List apiTestSteps = new ArrayList<>(); + data.forEach((apiTestRecord) -> { + if (apiTestRecord.isSuccess()) { + apiTestSteps.add(BeanUtil.copyProperties(apiTestRecord, ApiStep.class)); + } else { + throw new RuntimeException("some cases are failed, can't convert to api test step"); + } + }); + apiTestStepRepo.saveAll(apiTestSteps); + } +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/service/RemoteApiService.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/service/RemoteApiService.java new file mode 100644 index 0000000..27c3803 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/api/service/RemoteApiService.java @@ -0,0 +1,142 @@ +package io.fluent.qtm.api.service; + +import cn.hutool.core.bean.BeanUtil; +import io.fluent.postman.PostmanParser; +import io.fluent.postman.model.PostmanCollection; +import io.fluent.postman.model.PostmanItem; +import io.fluent.qtm.api.model.ApiSpecVersionModel; +import io.fluent.qtm.api.model.RemoteApi; +import io.fluent.qtm.api.model.RemoteApiStatus; +import io.fluent.qtm.api.repo.RemoteServiceRepo; +import io.fluent.base.product.model.ProductModuleModel; +import io.fluent.base.product.service.ProductModuleService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.List; +import java.util.Optional; + +@Service +@Slf4j +public class RemoteApiService { + + @Autowired + private ProductModuleService productMetaService; + + @Autowired + private RemoteServiceRepo remoteServiceRepo; + + + /** + * 1. 解析postman 文件 + * 2. 确认接口是 + * - 新增:NEW: 当前记录无记录,则更新 + * - 更新:UPDATED: 当前记录中有记录,但是接口定义发生变化,比如请求内容 + * - 使用中,IN_USE: + * - 移除:END_OF_LIFE: 接口不在最新清单中 + * 3. + * + * @param apiSpec + */ + @Transactional + public void apiSpecToApiList(ApiSpecVersionModel apiSpec, String updater) { + ProductModuleModel productMeta = productMetaService.createApiModuleIfNotExist(apiSpec.getName(), updater); + if (apiSpec.getSpec().isEmpty()) return; + PostmanCollection collection = PostmanParser.create().toPostmanCollection(apiSpec.getSpec()); + for (PostmanItem postmanItem : collection.getItem()) { + for (PostmanItem item : postmanItem.getItem()) { + RemoteApi rs = toRemoteApi(apiSpec, productMeta, postmanItem, item); + createOrUpdateRemoteApi(rs, apiSpec); + } + updateStatusToEndOfLife(apiSpec, postmanItem); + } + } + + @Transactional + public void apiSpecsToApiList(List apiSpecs, String updater) { + for (ApiSpecVersionModel apiSpec : apiSpecs) { + try { + this.apiSpecToApiList(apiSpec, updater); + } catch (Exception e) { + log.error("%s-api-failed,error=%s".formatted( + apiSpec.getName(), e.getMessage() + )); + } + } + } + + private RemoteApi toRemoteApi(ApiSpecVersionModel apiSpec, ProductModuleModel productMeta, + PostmanItem postmanItem, PostmanItem item) { + RemoteApi rs = new RemoteApi(); + rs.setName(item.getName()); + rs.setServiceName(postmanItem.getName()); + rs.setServiceMethod(item.getName()); + rs.setBody(item.getRequest().getBody().get("raw").toString()); + rs.setHttpMethod(item.getRequest().getMethod()); + rs.setEndpoint(item.getRequest().getUrl().getRaw()); + rs.setType(apiSpec.getServiceType()); + rs.setModuleName(apiSpec.getName()); + rs.setProductId(productMeta.getParent().getId()); + return rs; + } + + /** + * create or update 基本可以使用同一种方式处理 + * 1. 输入实体 + * 2. 字段检验规则 + * 3. 判断重复确认条件 + * 4. 更新字段处理,保存记录 + * TODO: try to integrate with Feishu + * + * @param newApi + */ + public void createOrUpdateRemoteApi(RemoteApi newApi, ApiSpecVersionModel apiSpec) { + Optional api = remoteServiceRepo.findRemoteApiByEndpointAndServiceNameAndServiceMethod( + newApi.getEndpoint(), + newApi.getServiceName(), + newApi.getServiceMethod()); + if (api.isEmpty()) { + newApi.setStatus(RemoteApiStatus.NEW.toString()); + newApi.setAddedVersion(apiSpec.getAppVersion()); + newApi.setLatestVersion(apiSpec.getAppVersion()); + remoteServiceRepo.save(newApi); + } else { + RemoteApi existApi = api.get(); + BeanUtil.copyProperties(newApi, existApi, "id"); + //TODO: 如何确认接口变更-暂时不确认 + if (existApi.getBody().equalsIgnoreCase(newApi.getBody())) { + existApi.setStatus(RemoteApiStatus.IN_USE.toString()); + existApi.setLatestVersion(apiSpec.getAppVersion()); + } else { + existApi.setStatus(RemoteApiStatus.UPDATED.toString()); + existApi.setLatestVersion(apiSpec.getAppVersion()); + } + remoteServiceRepo.save(existApi); + } + } + + public void updateStatusToEndOfLife(ApiSpecVersionModel apiSpec, PostmanItem postmanItem) { + Optional> apiListOptional = remoteServiceRepo.findRemoteApiByModuleNameAndServiceNameAndLatestVersionNot( + apiSpec.getName(), + postmanItem.getName(), + apiSpec.getAppVersion() + ); + if (apiListOptional.isEmpty()) { + log.info("没有需要删除的数据"); + } else { + List apiList = apiListOptional.get(); + for (RemoteApi api : apiList) { + api.setStatus(RemoteApiStatus.END_OF_LIFE.toString()); + remoteServiceRepo.save(api); + log.info("有需要删除的数据"); + } + + } + } + + +} + + diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/pm/package-info.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/pm/package-info.java new file mode 100644 index 0000000..b8c6392 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/pm/package-info.java @@ -0,0 +1 @@ +package io.fluent.qtm.pm; \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/pm/requirement/FieldOption.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/pm/requirement/FieldOption.java new file mode 100644 index 0000000..d0727ce --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/pm/requirement/FieldOption.java @@ -0,0 +1,158 @@ +package io.fluent.qtm.pm.requirement; + + +import io.fluent.base.model.ModelWithValidFlag; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.fun.ChoiceFetchHandler; +import xyz.erupt.annotation.fun.VLModel; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.sub_edit.ChoiceType; +import xyz.erupt.annotation.sub_field.sub_edit.CodeEditorType; + +import javax.persistence.Entity; +import javax.persistence.Table; +import java.util.ArrayList; +import java.util.List; + +@Entity +@Erupt(name = "字段选项", + power = @Power(export = true, importable = true), + orderBy = "FieldOption.updateTime desc") +@Table(name = "field_option") +public class FieldOption extends ModelWithValidFlag implements ChoiceFetchHandler { + @EruptField( + views = @View( + title = "名称" + ), + edit = @Edit( + title = "名称",notNull = true + ) + ) + private String name; + @EruptField( + views = @View( + title = "字段code" + ), + edit = @Edit( + title = "字段code" + ) + ) + private String code; + + @EruptField( + views = @View(title = "编辑类型"), + edit = @Edit(title = "编辑类型", + notNull = true, type = EditType.CHOICE, + choiceType = @ChoiceType(type = ChoiceType.Type.RADIO, fetchHandler = FieldOption.class)) + ) + private String type; + + @EruptField( + views = @View( + title = "是否可以为空" + ), + edit = @Edit( + title = "是否可以为空", + type = EditType.BOOLEAN + ) + ) + private boolean notNull; + @EruptField( + views = @View( + title = "字段约束条件" + ), + edit = @Edit( + title = "字段约束条件", + type = EditType.CODE_EDITOR, notNull = true, + codeEditType = @CodeEditorType(language = "text"), + desc = "字段约束条件" + ) + ) + private String constrains; + + @EruptField( + views = @View( + title = "和其他业务关系" + ), + edit = @Edit( + title = "和其他业务关系", + type = EditType.CODE_EDITOR, + codeEditType = @CodeEditorType(language = "text") + ) + ) + private String relatedTo; + + @EruptField( + views = @View(title = "显示顺序", sortable = true), + edit = @Edit(title = "显示顺序", notNull = true) + ) + private Integer sort; + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public boolean isNotNull() { + return notNull; + } + + public void setNotNull(boolean notNull) { + this.notNull = notNull; + } + + public String getConstrains() { + return constrains; + } + + public void setConstrains(String constrains) { + this.constrains = constrains; + } + + public String getRelatedTo() { + return relatedTo; + } + + public void setRelatedTo(String relatedTo) { + this.relatedTo = relatedTo; + } + + public Integer getSort() { + return sort; + } + + public void setSort(Integer sort) { + this.sort = sort; + } + + @Override + public List fetch(String[] params) { + List list = new ArrayList<>(); + for (FieldOptionType value : FieldOptionType.values()) { + list.add(new VLModel(value.name(), value.getDesc())); + } + return list; + } +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/pm/requirement/FieldOptionType.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/pm/requirement/FieldOptionType.java new file mode 100644 index 0000000..69b306b --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/pm/requirement/FieldOptionType.java @@ -0,0 +1,13 @@ +package io.fluent.qtm.pm.requirement; + +import lombok.Getter; + +@Getter +public enum FieldOptionType { + NUMBER("数值"),STRING("字符串"),RELATION("关联"),DATE("日期"),ENUM("枚举"),BOOLEAN("布尔"); + + private String desc; + FieldOptionType(String desc) { + this.desc = desc; + } +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/pm/requirement/RequirementFeature.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/pm/requirement/RequirementFeature.java new file mode 100644 index 0000000..a91ffc6 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/pm/requirement/RequirementFeature.java @@ -0,0 +1,34 @@ +package io.fluent.qtm.pm.requirement; + +import io.fluent.base.model.ModelWithValidFlag; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.sub_edit.CodeEditorType; + +import javax.persistence.Entity; +import javax.persistence.Table; + +@Entity +@Erupt(name = "需求功能点", + power = @Power(export = true, importable = true), + orderBy = "RequirementFeature.updateTime desc") +@Table(name = "requirement_features") +public class RequirementFeature extends ModelWithValidFlag { + + @EruptField( + views = @View( + title = "业务功能相关说明" + ), + edit = @Edit( + title = "业务功能相关说明", + type = EditType.CODE_EDITOR, notNull = true, + codeEditType = @CodeEditorType(language = "text") + ) + ) + private String feature; + +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/pm/requirement/RequirementType.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/pm/requirement/RequirementType.java new file mode 100644 index 0000000..23f7c44 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/pm/requirement/RequirementType.java @@ -0,0 +1,15 @@ +package io.fluent.qtm.pm.requirement; + +import lombok.Getter; + +@Getter +public enum RequirementType { + CREATE("创建"),UPDATE("更新"),DELETE("删除/归档"),SEARCH("查询"), COMPLEX("复杂业务"), + WORKFLOW("工作流"), + REPORT("报表"),OTHER("其他"); + + private String desc; + RequirementType(String desc) { + this.desc = desc; + } +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/pm/requirement/TestRequirement.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/pm/requirement/TestRequirement.java new file mode 100644 index 0000000..31a5222 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/pm/requirement/TestRequirement.java @@ -0,0 +1,192 @@ +package io.fluent.qtm.pm.requirement; + + +import io.fluent.base.handlers.SqlTagFetchHandler; +import io.fluent.base.model.ModelWithValidFlag; +import io.fluent.base.product.model.ProductModuleModel; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.fun.ChoiceFetchHandler; +import xyz.erupt.annotation.fun.VLModel; +import xyz.erupt.annotation.sub_erupt.LinkTree; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.sub_edit.ChoiceType; +import xyz.erupt.annotation.sub_field.sub_edit.ReferenceTreeType; +import xyz.erupt.annotation.sub_field.sub_edit.Search; +import xyz.erupt.annotation.sub_field.sub_edit.TagsType; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + + +@Entity +@Erupt(name = "测试需求管理", + power = @Power(export = true, importable = true), + orderBy = "TestRequirement.updateTime desc", + linkTree = @LinkTree(field = "module")) +@Table(name = "test_requirements") +public class TestRequirement extends ModelWithValidFlag implements ChoiceFetchHandler { + + @EruptField( + views = @View(title = "需求概述"), + edit = @Edit(title = "需求概述") + ) + private String summary; + + @EruptField( + views = @View(title = "需求类型"), + edit = @Edit(title = "需求类型", + notNull = true, type = EditType.CHOICE, + choiceType = @ChoiceType(type = ChoiceType.Type.RADIO, + fetchHandler = TestRequirement.class)) + ) + private String type; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name = "test_req_id") + @EruptField( + edit = @Edit(title = "功能点", type = EditType.TAB_TABLE_ADD) + ) + private Set features; + + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name = "test_req_id") + @OrderBy("sort") + @EruptField( + edit = @Edit(title = "字段管理", type = EditType.TAB_TABLE_ADD) + ) + private Set fieldOptions; + + @ManyToOne + @JoinColumn(name = "product_id") + @EruptField( + views = @View(title = "所属模块", column = "details"), + edit = @Edit( + notNull = true, + search = @Search, + title = "产品模块选择", + type = EditType.REFERENCE_TREE, + desc = "动态获取产品", + referenceTreeType = @ReferenceTreeType(id = "id", label = "name", + pid = "parent.id")) + ) + private ProductModuleModel module; + + @EruptField( + views = @View( + title = "提示词" + ), + edit = @Edit( + title = "提示词" + ) + ) + private String prompts; + + @EruptField( + views = @View( + title = "优先级" + ), + edit = @Edit( + search = @Search, + title = "优先级", + type = EditType.TAGS, + tagsType = @TagsType( + fetchHandler = SqlTagFetchHandler.class, + fetchHandlerParams = "select distinct key,detail from master_data where category_code = 'PRIORITY' order by 1 " + ) + ) + ) + private String priority = "P2"; + + @EruptField( + views = @View( + title = "需求状态" + ), + edit = @Edit( + title = "需求状态" + ) + ) + private String status; + + @Override + public List fetch(String[] params) { + List list = new ArrayList<>(); + for (RequirementType value : RequirementType.values()) { + list.add(new VLModel(value.name(), value.getDesc())); + } + return list; + } + + public String getPriority() { + return priority; + } + + public void setPriority(String priority) { + this.priority = priority; + } + + + public String getPrompts() { + return prompts; + } + + public void setPrompts(String prompts) { + this.prompts = prompts; + } + + + public Set getFieldOptions() { + return fieldOptions; + } + + public void setFieldOptions(Set fieldOptions) { + this.fieldOptions = fieldOptions; + } + + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Set getFeatures() { + return features; + } + + public void setFeatures(Set features) { + this.features = features; + } + + public String getSummary() { + return summary; + } + + public void setSummary(String summary) { + this.summary = summary; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public ProductModuleModel getModule() { + return module; + } + + public void setModule(ProductModuleModel module) { + this.module = module; + } +} \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/dto/TestCaseDTO.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/dto/TestCaseDTO.java new file mode 100644 index 0000000..bc776ff --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/dto/TestCaseDTO.java @@ -0,0 +1,28 @@ +package io.fluent.qtm.tc.dto; + +import com.github.crab2died.annotation.ExcelField; +import lombok.Data; + +@Data +public class TestCaseDTO { + @ExcelField(title = "产品名称") + private String productName; + @ExcelField(title = "模块名称") + private String moduleName; + @ExcelField(title = "功能点") + private String feature; + @ExcelField(title = "用例描述") + private String summary; + @ExcelField(title = "优先级") + private String priority = "P2"; //check it + @ExcelField(title = "用例前提条件") + private String precondition; + @ExcelField(title = "测试步骤") + private String steps; + @ExcelField(title = "期望结果") + private String expectedResult; + + @ExcelField(title = "用例ID") + private String uuid; + +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/handlers/GenerateTestRecordHandler.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/handlers/GenerateTestRecordHandler.java new file mode 100644 index 0000000..cc87109 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/handlers/GenerateTestRecordHandler.java @@ -0,0 +1,49 @@ +package io.fluent.qtm.tc.handlers; + + +import cn.hutool.core.bean.BeanUtil; +import io.fluent.qtm.tc.model.TestCase; +import io.fluent.qtm.tc.model.TestResult; +import io.fluent.qtm.tc.model.TestRun; +import io.fluent.qtm.tc.model.TestScenario; +import io.fluent.qtm.tc.repo.TestResultRepo; + +import org.springframework.stereotype.Service; +import xyz.erupt.annotation.fun.OperationHandler; + + +import javax.annotation.Resource; +import java.util.List; + +@Service +public class GenerateTestRecordHandler implements OperationHandler { + @Resource + private TestResultRepo testResultRepo; + + @Override + public String exec(List data, Void unused, String[] param) { + for (TestRun testRun : data) { + //get all test cases + for (TestCase testCase : testRun.getTestCases()) { + TestResult result = BeanUtil.copyProperties(testCase, TestResult.class); + result.setTestCaseUUID(testCase.getUuid()); + result.setTestRun(testRun); + result.setQaOwner(testRun.getTestOwner()); + testResultRepo.save(result); + } + for (TestScenario tc : testRun.getTestScenarios()) { + for (TestCase testCase : tc.getTestCases()) { + TestResult result = BeanUtil.copyProperties(testCase, TestResult.class); + result.setTestCaseUUID(testCase.getUuid()); + result.setTestRun(testRun); + result.setQaOwner(testRun.getTestOwner()); + result.setTestScenario(tc.getName()); + testResultRepo.save(result); + } + } + } + return null; + } + + +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/model/TestCase.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/model/TestCase.java new file mode 100644 index 0000000..2db1f68 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/model/TestCase.java @@ -0,0 +1,238 @@ +package io.fluent.qtm.tc.model; + +import io.fluent.base.handlers.SqlTagFetchHandler; +import io.fluent.base.model.ModelWithValidFlagVo; +import io.fluent.base.product.model.ProductModuleModel; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_erupt.Layout; +import xyz.erupt.annotation.sub_erupt.LinkTree; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.sub_edit.*; + +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +/** + * + */ +@Entity +@Erupt(name = "测试用例", + power = @Power(export = true), + orderBy = "TestCase.updateTime desc", + linkTree = @LinkTree(field = "module"),layout = @Layout( + tableLeftFixed = 3, + pageSize = 30)) +@Table(name = "test_cases") +public class TestCase extends ModelWithValidFlagVo { + + @ManyToOne + @JoinColumn(name = "product_id") + @EruptField( + views = @View(title = "所属模块",column = "details"), + edit = @Edit( + notNull = true, + search = @Search, + title = "产品模块选择", + type = EditType.REFERENCE_TREE, + desc = "动态获取产品", + referenceTreeType = @ReferenceTreeType(id = "id", label = "name", + pid = "parent.id")) + ) + private ProductModuleModel module; + + @ManyToOne + @JoinColumn(name = "parent_product_id") + @EruptField( + views = @View(title = "父模块",column = "details"), + edit = @Edit( + notNull = true, + search = @Search, + title = "产品模块选择", + type = EditType.REFERENCE_TREE, + desc = "动态获取产品", + referenceTreeType = @ReferenceTreeType(id = "id", label = "name", + pid = "parent.id")) + ) + private ProductModuleModel parent; + + @ManyToOne + @JoinColumn(name = "root_product_id") + @EruptField( + views = @View(title = "所属产品",column = "details"), + edit = @Edit( + notNull = true, + search = @Search, + title = "产品模块选择", + type = EditType.REFERENCE_TREE, + desc = "动态获取产品", + referenceTreeType = @ReferenceTreeType(id = "id", label = "name", + pid = "parent.id")) + ) + private ProductModuleModel product; + + @EruptField( + views = @View( + title = "功能点" + ), + edit = @Edit( + title = "功能点", + type = EditType.INPUT, search = @Search, notNull = true + ) + ) + private String feature; + @EruptField( + views = @View( + title = "用例描述" + ), + edit = @Edit( + title = "用例描述", + type = EditType.INPUT, notNull = true + ) + ) + private String summary; + + @EruptField( + views = @View( + title = "优先级" + ), + edit = @Edit( + title = "优先级", + type = EditType.TAGS, + search = @Search, + tagsType = @TagsType( + fetchHandler = SqlTagFetchHandler.class, + fetchHandlerParams = "select distinct key,detail from master_data where category_code = 'PRIORITY' order by 1 " + ) + ) + ) + private String priority = "P2"; + + + @EruptField( + views = @View( + title = "测试步骤" + ), + edit = @Edit( + title = "测试步骤", + type = EditType.CODE_EDITOR, notNull = true, + codeEditType = @CodeEditorType(language = "text") + ) + ) + private String steps; + @EruptField( + views = @View( + title = "期望结果" + ), + edit = @Edit( + title = "期望结果", + type = EditType.CODE_EDITOR, + codeEditType = @CodeEditorType(language = "text") + ) + ) + private String expectedResult; + + @EruptField( + views = @View( + title = "用例ID" + ) + ) + private String uuid; + @EruptField( + views = @View( + title = "用例前提条件" + ), + edit = @Edit( + title = "用例前提条件", + type = EditType.CODE_EDITOR, + codeEditType = @CodeEditorType(language = "text") + ) + ) + private String precondition; + + public String getFeature() { + return feature; + } + + public void setFeature(String feature) { + this.feature = feature; + } + + public String getSummary() { + return summary; + } + + public void setSummary(String summary) { + this.summary = summary; + } + + public String getPriority() { + return priority; + } + + public void setPriority(String priority) { + this.priority = priority; + } + + public String getSteps() { + return steps; + } + + public void setSteps(String steps) { + this.steps = steps; + } + + public String getExpectedResult() { + return expectedResult; + } + + public void setExpectedResult(String expectedResult) { + this.expectedResult = expectedResult; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getPrecondition() { + return precondition; + } + + public void setPrecondition(String precondition) { + this.precondition = precondition; + } + + + public ProductModuleModel getModule() { + return module; + } + + public void setModule(ProductModuleModel module) { + this.module = module; + } + + public ProductModuleModel getParent() { + return parent; + } + + public void setParent(ProductModuleModel parent) { + this.parent = parent; + } + + public ProductModuleModel getProduct() { + return product; + } + + public void setProduct(ProductModuleModel product) { + this.product = product; + } +} \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/model/TestResult.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/model/TestResult.java new file mode 100644 index 0000000..63039fb --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/model/TestResult.java @@ -0,0 +1,206 @@ +package io.fluent.qtm.tc.model; + + +import io.fluent.base.model.ModelWithValidFlagVo; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_erupt.LinkTree; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.sub_edit.CodeEditorType; +import xyz.erupt.annotation.sub_field.sub_edit.ReferenceTreeType; +import xyz.erupt.annotation.sub_field.sub_edit.Search; + +import javax.persistence.Entity; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + + +@Table(name = "test_results") +@Entity +@Erupt(name = "测试执行结果", + power = @Power(importable = true, export = true) + , linkTree = @LinkTree(field = "testRun") +) +public class TestResult extends ModelWithValidFlagVo { + @ManyToOne + @EruptField( + views = @View(title = "所属测试安排", column = "name"), + edit = @Edit(title = "所属测试安排", type = EditType.REFERENCE_TREE, + referenceTreeType = @ReferenceTreeType(pid = "parent.id", expandLevel = 2)) + ) + private TestRun testRun; + + @EruptField( + views = @View( + title = "测试场景" + ), + edit = @Edit( + title = "测试场景", + type = EditType.INPUT, search = @Search, notNull = true + ) + ) + private String testScenario; + @EruptField( + views = @View( + title = "功能点" + ), + edit = @Edit( + title = "功能点", + type = EditType.INPUT, search = @Search, notNull = true + ) + ) + private String feature; + @EruptField( + views = @View( + title = "用例描述" + ), + edit = @Edit( + title = "用例描述", + type = EditType.INPUT, notNull = true + ) + ) + private String summary; + @EruptField( + views = @View( + title = "用例优先级" + ), + edit = @Edit( + title = "用例优先级", + type = EditType.INPUT, search = @Search, notNull = true + ) + ) + private String priority = "P2"; //check it + @EruptField( + views = @View( + title = "测试步骤" + ), + edit = @Edit( + title = "测试步骤", + type = EditType.CODE_EDITOR, notNull = true, + codeEditType = @CodeEditorType(language = "text") + ) + ) + private String steps; + @EruptField( + views = @View( + title = "用例期望结果" + ), + edit = @Edit( + title = "用例期望结果", + type = EditType.CODE_EDITOR, notNull = true, + codeEditType = @CodeEditorType(language = "text") + ) + ) + private String expectedResult; + + + @EruptField( + views = @View( + title = "测试测试结果" + ), + edit = @Edit( + title = "测试测试结果", + type = EditType.INPUT, search = @Search, notNull = true + ) + ) + private String qaTestResult; + + + @EruptField( + views = @View( + title = "测试负责人" + ), + edit = @Edit( + title = "测试负责人", + type = EditType.INPUT, search = @Search, notNull = true + ) + ) + private String qaOwner; + + private String testCaseUUID; + + + public String getTestCaseUUID() { + return testCaseUUID; + } + + public void setTestCaseUUID(String testCaseUUID) { + this.testCaseUUID = testCaseUUID; + } + + public String getFeature() { + return feature; + } + + public void setFeature(String feature) { + this.feature = feature; + } + + public String getSummary() { + return summary; + } + + public void setSummary(String summary) { + this.summary = summary; + } + + public String getPriority() { + return priority; + } + + public void setPriority(String priority) { + this.priority = priority; + } + + public String getSteps() { + return steps; + } + + public void setSteps(String steps) { + this.steps = steps; + } + + public String getExpectedResult() { + return expectedResult; + } + + public void setExpectedResult(String expectedResult) { + this.expectedResult = expectedResult; + } + + + public String getQaTestResult() { + return qaTestResult; + } + + public void setQaTestResult(String qaTestResult) { + this.qaTestResult = qaTestResult; + } + + public String getQaOwner() { + return qaOwner; + } + + public void setQaOwner(String qaOwner) { + this.qaOwner = qaOwner; + } + + public TestRun getTestRun() { + return testRun; + } + + public void setTestRun(TestRun testRun) { + this.testRun = testRun; + } + + public String getTestScenario() { + return testScenario; + } + + public void setTestScenario(String testScenario) { + this.testScenario = testScenario; + } +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/model/TestRun.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/model/TestRun.java new file mode 100644 index 0000000..47c9af6 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/model/TestRun.java @@ -0,0 +1,251 @@ +package io.fluent.qtm.tc.model; + + +import io.fluent.base.product.model.ProductModuleModel; +import io.fluent.qtm.tc.handlers.GenerateTestRecordHandler; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_erupt.RowOperation; +import xyz.erupt.annotation.sub_erupt.Tree; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.sub_edit.BoolType; +import xyz.erupt.annotation.sub_field.sub_edit.ReferenceTreeType; +import xyz.erupt.annotation.sub_field.sub_edit.Search; +import xyz.erupt.jpa.model.MetaModel; + +import javax.persistence.*; +import java.time.LocalDate; +import java.util.Set; + +//TODO: Filter By Status +//TODO: input by Uploaded File or File Sync +@Entity +@Table(name = "test_runs") +@Erupt(name = "测试执行计划", + power = @Power(importable = true, export = true), + tree = @Tree(id = "id", label = "name", pid = "parent.id") + ,rowOperation = {@RowOperation( + title = "生成执行测试用例", + operationHandler = GenerateTestRecordHandler.class)} +) + +public class TestRun extends MetaModel { + + @ManyToOne + @JoinColumn(name = "product_id") + @EruptField( + views = @View(title = "产品名称", column = "name"), + edit = @Edit( + search = @Search, + title = "产品选择", + type = EditType.REFERENCE_TREE, + desc = "动态获取产品", + referenceTreeType = @ReferenceTreeType( + pid = "parent.id")) + ) + private ProductModuleModel product; + + @ManyToOne + @EruptField( + edit = @Edit( + title = "父级测试安排", + type = EditType.REFERENCE_TREE, + referenceTreeType = @ReferenceTreeType(pid = "parent.id") + ) + ) + private TestRun parent; + + + @EruptField( + views = @View( + title = "测试负责人" + ), + edit = @Edit( + title = "测试负责人", + type = EditType.INPUT, search = @Search + ) + ) + private String testOwner; + + @JoinTable(name = "test_run_cases", + joinColumns = @JoinColumn(name = "test_run_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "test_case_id", referencedColumnName = "id")) + @ManyToMany(fetch = FetchType.EAGER) + @EruptField( + views = @View(title = "包含用例"), + edit = @Edit( + title = "包含用例", + type = EditType.TAB_TABLE_REFER + ) + ) + private Set testCases; + + @JoinTable(name = "test_run_scenario", + joinColumns = @JoinColumn(name = "test_run_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "test_scenario_id", referencedColumnName = "id")) + @ManyToMany(fetch = FetchType.EAGER) + @EruptField( + views = @View(title = "包含测试场景"), + edit = @Edit( + title = "包含测试场景", + type = EditType.TAB_TABLE_REFER + ) + ) + private Set testScenarios; + + public ProductModuleModel getProduct() { + return product; + } + + public void setProduct(ProductModuleModel product) { + this.product = product; + } + + public String getTestOwner() { + return testOwner; + } + + public void setTestOwner(String testOwner) { + this.testOwner = testOwner; + } + + public Set getTestCases() { + return testCases; + } + + public void setTestCases(Set testCases) { + this.testCases = testCases; + } + + public Set getTestScenarios() { + return testScenarios; + } + + public void setTestScenarios(Set testScenarios) { + this.testScenarios = testScenarios; + } + + public TestRun getParent() { + return parent; + } + + public void setParent(TestRun parent) { + this.parent = parent; + } + + @EruptField( + views = @View( + title = "名称" + ), + edit = @Edit( + title = "名称", + type = EditType.INPUT, search = @Search, notNull = true + ) + ) + private String name; + @EruptField( + views = @View( + title = "详细" + ), + edit = @Edit( + title = "详细", + type = EditType.INPUT, search = @Search, notNull = true + ) + ) + private String detail; + @EruptField( + views = @View( + title = "开始时间" + ), + edit = @Edit( + title = "开始时间", + type = EditType.DATE, search = @Search, + boolType = @BoolType + ) + ) + private LocalDate startDate; + @EruptField( + views = @View( + title = "预计完成时间" + ), + edit = @Edit( + title = "预计完成时间", + type = EditType.DATE, search = @Search, + boolType = @BoolType + ) + ) + private LocalDate estimatedCompletedDate; + @EruptField( + views = @View( + title = "完成时间" + ), + edit = @Edit( + title = "完成时间", + type = EditType.DATE, search = @Search, + boolType = @BoolType + ) + ) + private LocalDate completedDate; + @EruptField( + views = @View( + title = "当前状态" + ), + edit = @Edit( + title = "当前状态", + type = EditType.INPUT, search = @Search, notNull = true, + boolType = @BoolType + ) + ) + private String status; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDetail() { + return detail; + } + + public void setDetail(String detail) { + this.detail = detail; + } + + public LocalDate getStartDate() { + return startDate; + } + + public void setStartDate(LocalDate startDate) { + this.startDate = startDate; + } + + public LocalDate getEstimatedCompletedDate() { + return estimatedCompletedDate; + } + + public void setEstimatedCompletedDate(LocalDate estimatedCompletedDate) { + this.estimatedCompletedDate = estimatedCompletedDate; + } + + public LocalDate getCompletedDate() { + return completedDate; + } + + public void setCompletedDate(LocalDate completedDate) { + this.completedDate = completedDate; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/model/TestScenario.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/model/TestScenario.java new file mode 100644 index 0000000..58478ab --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/model/TestScenario.java @@ -0,0 +1,43 @@ +package io.fluent.qtm.tc.model; + +import io.fluent.base.model.NamedModelVO; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; + +import javax.persistence.*; +import java.util.Set; + +@Entity +@Table(name = "test_scenarios") +@Erupt(name = "测试场景管理", + power = @Power(importable = true, export = true) +) +//@PreDataProxy(value= TestScenarioCaseProxy.class) + +public class TestScenario extends NamedModelVO { + + @JoinTable(name = "test_scenario_cases", + joinColumns = @JoinColumn(name = "test_scenario_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "test_case_id", referencedColumnName = "id")) + @ManyToMany(fetch = FetchType.EAGER) + @EruptField( + views = @View(title = "包含用例"), + edit = @Edit( + title = "包含用例", + type = EditType.TAB_TABLE_REFER + ) + ) + private Set testCases; + + public Set getTestCases() { + return testCases; + } + + public void setTestCases(Set testCases) { + this.testCases = testCases; + } +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/package-info.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/package-info.java new file mode 100644 index 0000000..0f28f0f --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/package-info.java @@ -0,0 +1 @@ +package io.fluent.qtm.tc; \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/repo/TestCaseRepo.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/repo/TestCaseRepo.java new file mode 100644 index 0000000..354138a --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/repo/TestCaseRepo.java @@ -0,0 +1,15 @@ +package io.fluent.qtm.tc.repo; + +import io.fluent.qtm.tc.model.TestCase; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface TestCaseRepo extends JpaRepository { + public TestCase findByUuid(String uuid); + + +// @Query(nativeQuery = true,value = "delete from test_cases where test_plan=:testPlan") +// @Modifying +// public void deleteByTestPlan(@Param("testPlan") String testPlan); +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/repo/TestResultRepo.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/repo/TestResultRepo.java new file mode 100644 index 0000000..570f55a --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/repo/TestResultRepo.java @@ -0,0 +1,11 @@ +package io.fluent.qtm.tc.repo; + + +import io.fluent.qtm.tc.model.TestResult; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository(value = "testResultRepo") +public interface TestResultRepo extends JpaRepository { + +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/repo/TestRunRepo.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/repo/TestRunRepo.java new file mode 100644 index 0000000..f84b76c --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/repo/TestRunRepo.java @@ -0,0 +1,11 @@ +package io.fluent.qtm.tc.repo; + + +import io.fluent.qtm.tc.model.TestRun; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface TestRunRepo extends JpaRepository { + +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/service/TestCaseService.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/service/TestCaseService.java new file mode 100644 index 0000000..d4cda3f --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/service/TestCaseService.java @@ -0,0 +1,14 @@ +package io.fluent.qtm.tc.service; + +import io.fluent.base.product.model.ProductModuleModel; +import io.fluent.qtm.tc.dto.TestCaseDTO; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public interface TestCaseService { + + public void saveTestCases(List cases, + ProductModuleModel product, ProductModuleModel module,String updater); +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/service/impl/MindMappingService.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/service/impl/MindMappingService.java new file mode 100644 index 0000000..28dad0b --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/service/impl/MindMappingService.java @@ -0,0 +1,41 @@ +package io.fluent.qtm.tc.service.impl; + + + +import cn.hutool.core.bean.BeanUtil; +import io.fluent.base.product.model.ProductModuleModel; +import io.fluent.qtm.tc.dto.TestCaseDTO; +import io.fluent.qtm.tc.service.TestCaseService; +import io.fluent.mindmap.api.MindMapAccessor; +import org.springframework.stereotype.Service; +import xyz.erupt.jpa.model.MetaModel; + +import javax.annotation.Resource; +import javax.transaction.Transactional; +import java.util.List; + +/** + * 1.Import MindMapping file to test case database + * 2.export selected test cases as mindmapping file + */ +//TODO: convert to same TestCase Converter +@Service("mindMappingService") +public class MindMappingService { + + @Resource + private TestCaseService testCaseService; + + public List toTestCaseModel(String xmlFilePath) { + MindMapAccessor accessor = new MindMapAccessor(); + return accessor.readMindMapToBean(xmlFilePath, TestCaseDTO.class); + } + + @Transactional + public void saveTestCases(String xmlFilePath, MetaModel model) { + List testCaseModels = toTestCaseModel(xmlFilePath); + ProductModuleModel product = BeanUtil.getProperty(model, "product"); + ProductModuleModel module = BeanUtil.getProperty(model, "module"); + testCaseService.saveTestCases(testCaseModels,product,module,model.getUpdateBy()); + } + +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/service/impl/TestCaseServiceImpl.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/service/impl/TestCaseServiceImpl.java new file mode 100644 index 0000000..7fdb66d --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/tc/service/impl/TestCaseServiceImpl.java @@ -0,0 +1,94 @@ +package io.fluent.qtm.tc.service.impl; + + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.lang.UUID; +import cn.hutool.core.util.StrUtil; +import io.fluent.base.proxies.AuditDataEnhancerProxy; +import io.fluent.base.product.model.ProductModuleModel; +import io.fluent.base.product.service.ProductModuleService; +import io.fluent.qtm.tc.dto.TestCaseDTO; +import io.fluent.qtm.tc.model.TestCase; +import io.fluent.qtm.tc.repo.TestCaseRepo; +import io.fluent.qtm.tc.service.TestCaseService; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import javax.transaction.Transactional; +import java.util.List; + +@Service +public class TestCaseServiceImpl implements TestCaseService { + @Resource + private TestCaseRepo testCaseRepo; + @Resource + private ProductModuleService productMetaService; + + @Resource + private AuditDataEnhancerProxy dataEnhancerProxy; + @Override + @Transactional + @Async + /** + * notice:parent Product can't be created,parent product must be configured + * 1. 如果UUID没有或者找不到,则新增测试用例 + * 2. 新增测试用例中, + */ + public void saveTestCases(List cases, + ProductModuleModel parentProduct, + ProductModuleModel module,String updater) { + for (TestCaseDTO aCase : cases) { + TestCase tcEntity = createOrUseExistingTestCase(aCase); + ProductModuleModel rootProduct = getRootProductMeta(aCase); + ProductModuleModel parentModule = productMetaService.createModuleIfNotExist(rootProduct.getId(), + aCase.getModuleName(),updater); + ProductModuleModel subModule = whichSubModule(parentModule, aCase,updater); + tcEntity.setModule(subModule); + tcEntity.setProduct(rootProduct); + tcEntity.setParent(parentModule); + if (StrUtil.isBlankIfStr(aCase.getPriority())) { + tcEntity.setPriority("P2"); + } + tcEntity.setSteps(StrUtil.join(":\n", aCase.getFeature(), + aCase.getSummary(), aCase.getSteps())); + + testCaseRepo.save(tcEntity); + } + } + + private TestCase createOrUseExistingTestCase(TestCaseDTO aCase) { + TestCase tcEntity; + if (StrUtil.isBlank(aCase.getUuid())) { + tcEntity = BeanUtil.copyProperties(aCase, TestCase.class); + tcEntity.setUuid(UUID.fastUUID().toString(true)); + + } else { + tcEntity = testCaseRepo.findByUuid(aCase.getUuid()); + if (tcEntity == null) { + tcEntity = BeanUtil.copyProperties(aCase, TestCase.class); //生成新的的UUID + } else { + BeanUtil.copyProperties(aCase, tcEntity, "id"); //更新数据库数据 + } + } + return tcEntity; + } + + + private ProductModuleModel getRootProductMeta(TestCaseDTO aCase) { + ProductModuleModel rootProductMeta = productMetaService.findByName(aCase.getProductName()); + if (rootProductMeta == null) { + throw new RuntimeException("找不到产品"); + } + return rootProductMeta; + } + + + private ProductModuleModel whichSubModule(ProductModuleModel parentProduct, TestCaseDTO aCase,String updater) { + if (parentProduct.getName().equalsIgnoreCase(aCase.getModuleName())) return parentProduct; + return productMetaService.createModuleIfNotExist(parentProduct.getId(), aCase.getModuleName(),updater); + + } + + +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/upload/model/UploadFileModel.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/upload/model/UploadFileModel.java new file mode 100644 index 0000000..bf185b0 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/upload/model/UploadFileModel.java @@ -0,0 +1,62 @@ +package io.fluent.qtm.upload.model; + +import io.fluent.base.product.model.ProductModuleModel; +import io.fluent.qtm.upload.proxy.UploadFileDataProxy; +import lombok.Data; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.PreDataProxy; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.sub_edit.AttachmentType; +import xyz.erupt.annotation.sub_field.sub_edit.ChoiceType; +import xyz.erupt.annotation.sub_field.sub_edit.InputType; +import xyz.erupt.annotation.sub_field.sub_edit.Search; +import xyz.erupt.toolkit.handler.SqlChoiceFetchHandler; + +import javax.persistence.Entity; +import javax.persistence.Table; + +@Erupt(name = "测试相关文件上传同步", orderBy = "UploadFileModel.createTime desc") +@Table(name = "uploaded_files") +@Entity +@Data +@PreDataProxy(value = UploadFileDataProxy.class) +public class UploadFileModel extends ProductModuleModel { + + @EruptField( + views = @View(title = "用途"), + edit = @Edit( + search = @Search, + title = "获取可选类型", + type = EditType.CHOICE, + desc = "动态获取可选类型", + notNull = true, + choiceType = @ChoiceType( + fetchHandler = SqlChoiceFetchHandler.class, + fetchHandlerParams = "select distinct code,name from master_data where category='UPLOAD_FILE_USAGE' and valid=true" + )) + ) + private String usage; + + + @EruptField( + views = @View(title = "文件上传"), + edit = @Edit(title = "文件上传", type = EditType.ATTACHMENT, + attachmentType = @AttachmentType(size = 100000)) + ) + private String attachment; + + @EruptField( + views = @View( + title = "用途描述" + ), + edit = @Edit( + title = "用途描述", + type = EditType.TEXTAREA, notNull = true, + inputType = @InputType + ) + ) + private String comments; +} \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/upload/package-info.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/upload/package-info.java new file mode 100644 index 0000000..3a084f9 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/upload/package-info.java @@ -0,0 +1 @@ +package io.fluent.qtm.upload; \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/upload/proxy/UploadFileDataProxy.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/upload/proxy/UploadFileDataProxy.java new file mode 100644 index 0000000..193c7ca --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/upload/proxy/UploadFileDataProxy.java @@ -0,0 +1,64 @@ +package io.fluent.qtm.upload.proxy; + + + +import cn.hutool.core.bean.BeanUtil; +import io.fluent.excel.ExcelReadWriter; +import io.fluent.base.product.model.ProductModuleModel; +import io.fluent.qtm.tc.dto.TestCaseDTO; +import io.fluent.qtm.tc.service.TestCaseService; +import io.fluent.qtm.tc.service.impl.MindMappingService; +import lombok.extern.slf4j.Slf4j; +import xyz.erupt.core.prop.EruptProp; +import xyz.erupt.core.util.EruptSpringUtil; +import xyz.erupt.jpa.model.MetaDataProxy; +import xyz.erupt.jpa.model.MetaModel; + +import java.util.List; + +@Slf4j +public class UploadFileDataProxy extends MetaDataProxy { + private final MindMappingService mindMappingService; + private final TestCaseService testCaseService; + private final EruptProp eruptProp; + private final ExcelReadWriter excelReadWriter; + + public UploadFileDataProxy() { + mindMappingService = EruptSpringUtil.getBean(MindMappingService.class); + testCaseService = EruptSpringUtil.getBean(TestCaseService.class); + eruptProp = EruptSpringUtil.getBean(EruptProp.class); + excelReadWriter = new ExcelReadWriter(); + } + + @Override + public void beforeAdd(MetaModel metaModel) { + //before add, add some check here + super.beforeAdd(metaModel); + } + + @Override + public void afterAdd(MetaModel metaModel) { + //after add, then doing business process + log.info("start handler uploaded file"); + String filePath = getUploaderFilePath(metaModel); + String uploadType = BeanUtil.getProperty(metaModel, "usage"); + + if(UploadFileTypeEnum.parseType(uploadType).equals(UploadFileTypeEnum.EXCEL_TC)){ + ProductModuleModel product = BeanUtil.getProperty(metaModel, "product"); + ProductModuleModel module = BeanUtil.getProperty(metaModel, "module"); + testCaseService.saveTestCases(getExcelTestCases(filePath),product,module,metaModel.getUpdateBy()); + } + if(UploadFileTypeEnum.parseType(uploadType).equals(UploadFileTypeEnum.FREEMIND)){ + mindMappingService.saveTestCases(filePath,metaModel); + } + } + + private List getExcelTestCases(String filePath){ + return excelReadWriter.readExcel(filePath, TestCaseDTO.class); + } + + private String getUploaderFilePath(MetaModel metaModel) { + return eruptProp.getUploadPath() + BeanUtil.getProperty(metaModel, "attachment"); + } + +} diff --git a/fluent-apps/workspace/src/main/java/io/fluent/qtm/upload/proxy/UploadFileTypeEnum.java b/fluent-apps/workspace/src/main/java/io/fluent/qtm/upload/proxy/UploadFileTypeEnum.java new file mode 100644 index 0000000..7854549 --- /dev/null +++ b/fluent-apps/workspace/src/main/java/io/fluent/qtm/upload/proxy/UploadFileTypeEnum.java @@ -0,0 +1,14 @@ +package io.fluent.qtm.upload.proxy; + +public enum UploadFileTypeEnum { + EXCEL_TC,FREEMIND,PM,MINDMAP; + + public static UploadFileTypeEnum parseType(String uploadFileType) { + for (UploadFileTypeEnum uploadFileTypeEnum : UploadFileTypeEnum.values()) { + if (uploadFileTypeEnum.name().equals(uploadFileType)) { + return uploadFileTypeEnum; + } + } + throw new RuntimeException("UploadFileTypeEnum is not found for " + uploadFileType); + } +} diff --git a/fluent-apps/feeds/src/main/resources/application-dev.yaml b/fluent-apps/workspace/src/main/resources/application-dev.yaml similarity index 71% rename from fluent-apps/feeds/src/main/resources/application-dev.yaml rename to fluent-apps/workspace/src/main/resources/application-dev.yaml index 17106a1..97197cc 100644 --- a/fluent-apps/feeds/src/main/resources/application-dev.yaml +++ b/fluent-apps/workspace/src/main/resources/application-dev.yaml @@ -21,9 +21,20 @@ erupt: # 是否记录操作日志,默认true,该功能开启后可在【系统管理 → 操作日志】中查看操作日志 security.recordOperateLog: false +#spring: +# datasource: +# url: jdbc:postgresql://db.supabase.orb.local:5432/postgres?currentSchema=workspace +# username: postgres +# password: postgres +# jpa: +# show-sql: true +# generate-ddl: true +# database-platform: org.hibernate.dialect.PostgreSQLDialect +# database: postgresql + spring: datasource: - url: jdbc:postgresql://db.supabase.orb.local:5432/feeds + url: jdbc:postgresql://db.supabase.orb.local:5432/workspace username: postgres password: postgres jpa: @@ -31,7 +42,6 @@ spring: generate-ddl: true database-platform: org.hibernate.dialect.PostgreSQLDialect database: postgresql - # mail: # username: xxxx@qq.com # password: xxxxxxx @@ -62,8 +72,7 @@ knife4j: enable: true openapi: title: QA Workspace API - description: "`QA Workspace API - # workspace" + description: "`QA Workspace API workspace" email: fluentqa@163.com concat: fluent-qa # url: https://docs.xiaominfo.com @@ -88,12 +97,32 @@ server: includeStacktrace: ALWAYS includeMessage: ALWAYS port: 9090 + +# Enhanced logging configuration logging: level: - root: DEBUG - org.hibernate: DEBUG + root: INFO + io.fluentqa: DEBUG + org.hibernate: INFO io.fluent: DEBUG xyz.erupt: DEBUG + org.springframework: DEBUG + org.springframework.boot: DEBUG + org.springframework.boot.autoconfigure: DEBUG + org.springframework.context: DEBUG + org.springframework.beans: DEBUG + org.springframework.jdbc: DEBUG + org.springframework.orm: DEBUG + org.hibernate.SQL: DEBUG + org.hibernate.type.descriptor.sql: TRACE + pattern: + console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" + file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" + file: + name: ../temp/qam-application.log + +# Enable Spring Boot debug mode +debug: true magic-api: web: /fluentapi/v1 diff --git a/fluent-apps/feeds/src/main/resources/application.yaml b/fluent-apps/workspace/src/main/resources/application.yaml similarity index 100% rename from fluent-apps/feeds/src/main/resources/application.yaml rename to fluent-apps/workspace/src/main/resources/application.yaml diff --git a/fluent-apps/workspace/src/main/resources/public/app.css b/fluent-apps/workspace/src/main/resources/public/app.css new file mode 100644 index 0000000..44c63ae --- /dev/null +++ b/fluent-apps/workspace/src/main/resources/public/app.css @@ -0,0 +1,24 @@ +layout-header { + background: #3f51b5 !important; +} + +/* 例:修改登录页样式 */ +layout-passport > .container { + background-position: center !important; + background-repeat: repeat !important; + background-size: cover !important; + background-color: #fff !important; + background-image: url(https://www.erupt.xyz/demo/login-bg.svg) !important; +} + +layout-passport .title { + font-family: Courier New, Menlo, Monaco, Consolas, monospace !important; +} + +layout-passport form { + padding: 26px !important; + margin: 8px !important; + background: rgba(255, 255, 255, 0.9); + border-radius: 3px; + box-shadow: 1px 1px 10px rgba(190, 184, 184, 0.3); +} \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/resources/public/app.js b/fluent-apps/workspace/src/main/resources/public/app.js new file mode 100644 index 0000000..c4435ce --- /dev/null +++ b/fluent-apps/workspace/src/main/resources/public/app.js @@ -0,0 +1,71 @@ +window.eruptSiteConfig = { + //erupt接口地址,在前后端分离时指定 + domain: "", + //附件地址,一般情况下不需要指定,如果自定义对象存储空间,则需在此指定附件资源访问地址 + fileDomain: "", + //标题 + title: "QA Workspace", + //描述 + desc: "QA Base", + //是否展示版权信息 + copyright: true, + //高德地图 api key,使用地图组件须指定此属性,amapKey获取地址:https://lbs.amap.com (服务平台为:Web端(JS API)) + amapKey: "xxxx", + //高德地图 SecurityJsCode + amapSecurityJsCode: "xxxxx", + //logo路径 + logoPath: "erupt.svg", + //logo文字 + logoText: "erupt", + //注册页地址(仅是一个链接,需要自定义实际样式) + registerPage: "", + //自定义导航栏按钮,配置后将会出现在页面右上角 + r_tools: [{ + text: "自定义功能按钮", + icon: "fa-eercast", + mobileHidden: true, + click: function (event) { + alert("Function button"); + } + }], + // //登录成功事件 + // login: function(user){ + // + // }, + // //注销事件 + // logout: function(user){ + // + // } +}; + +// //路由回调函数 +// window.eruptRouterEvent = { +// //key表示要监听的路由切换地址,为url hash地址最后一段 +// //例如:http://www.erupt.xyz:9999/#/build/table/demo中demo为回调key +// demo: { +// //路由载入事件 +// load: function (e) { +// +// }, +// //路由退出事件 +// unload: function (e) { +// +// } +// }, +// //$ 为全路径通配符,在任何路由切换时都会执行load与unload事件 +// $: { +// load: function (e) { +// +// }, +// unload: function (e) { +// } +// } +// }; +// +// //erupt生命周期函数 +// window.eruptEvent = { +// //页面加载完成后回调 +// startup: function () { +// +// } +// } \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/resources/public/home.html b/fluent-apps/workspace/src/main/resources/public/home.html new file mode 100644 index 0000000..35600cf --- /dev/null +++ b/fluent-apps/workspace/src/main/resources/public/home.html @@ -0,0 +1,12 @@ + + + + home + + + + + +

测试管理工具箱

+ + \ No newline at end of file diff --git a/fluent-apps/workspace/src/main/resources/tpl/operation.tpl b/fluent-apps/workspace/src/main/resources/tpl/operation.tpl new file mode 100644 index 0000000..d77f7e5 --- /dev/null +++ b/fluent-apps/workspace/src/main/resources/tpl/operation.tpl @@ -0,0 +1,17 @@ + +
+ + <#list rows as row> + + + + + + +
${row.id}${row.choice!''}${row.code!''}
+
\ No newline at end of file diff --git a/fluent-erupts/fleunt-github/pom.xml b/fluent-erupts/fleunt-github/pom.xml index 40ea14e..2474f80 100644 --- a/fluent-erupts/fleunt-github/pom.xml +++ b/fluent-erupts/fleunt-github/pom.xml @@ -45,7 +45,7 @@ io.fluent fluent-git 1.0-SNAPSHOT - compile + \ No newline at end of file diff --git a/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/FluentGithubModule.java b/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/FluentGithubModule.java index 4ac5ad3..1535f73 100644 --- a/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/FluentGithubModule.java +++ b/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/FluentGithubModule.java @@ -2,6 +2,7 @@ import io.fluent.github.model.AwesomeResource; import io.fluent.github.model.GithubStarredRepo; +import io.fluent.github.model.GithubTrendingRepo; import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.ComponentScan; @@ -51,6 +52,12 @@ public List initMenus() { awesomeModule.setName("awesomes"); awesomeModule.setCode("$awesomes"); menus.add(awesomeModule); + + MetaMenu trendingReposModule = MetaMenu.createEruptClassMenu(GithubTrendingRepo.class, menus.get(0), 2, MenuTypeEnum.TABLE); + trendingReposModule.setIcon("fa fa-star"); + trendingReposModule.setName("github trending"); + trendingReposModule.setCode("$github-trending"); + menus.add(trendingReposModule); return menus; } diff --git a/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/jobs/GithubStarredCollectorJob.java b/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/jobs/GithubStarredCollectorJob.java index dad8c8a..ecc6137 100644 --- a/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/jobs/GithubStarredCollectorJob.java +++ b/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/jobs/GithubStarredCollectorJob.java @@ -5,6 +5,7 @@ import io.fluent.github.service.GithubService; import io.fluent.github.jobs.github.GithubJobFetchParameters; import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import xyz.erupt.core.annotation.EruptHandlerNaming; import xyz.erupt.job.handler.EruptJobHandler; @@ -32,11 +33,15 @@ public String exec(String code, String param) { }else { parameters = JSONUtil.toBean(param, GithubJobFetchParameters.class); } + saveGithubRepos(parameters); + return "success"; + } + + private void saveGithubRepos(GithubJobFetchParameters parameters) { List userNames=StringUtils.split(parameters.getUserNames(),","); for (String userName : userNames) { - githubService.saveUserStarredRepo(userName,parameters.getFromPage()); + githubService.saveUserStarredRepo(userName, parameters.getFromPage()); } - return "success"; } diff --git a/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/model/GithubStarredRepo.java b/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/model/GithubStarredRepo.java index 38cff49..596f044 100644 --- a/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/model/GithubStarredRepo.java +++ b/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/model/GithubStarredRepo.java @@ -23,8 +23,11 @@ public class GithubStarredRepo extends MetaModelVo { @EruptField(views = @View(title = "名称"), edit = @Edit(title = "名称", type = EditType.INPUT, search = @Search, notNull = true, inputType = @InputType)) private String name; + @EruptField(views = @View(title = "htmlUrl"), edit = @Edit(title = "htmlUrl", type = EditType.INPUT, search = @Search, notNull = true, inputType = @InputType)) + private String htmlUrl; @EruptField(views = @View(title = "URL"), edit = @Edit(title = "URL", type = EditType.INPUT, search = @Search, notNull = true, inputType = @InputType)) private String url; + @EruptField(views = @View(title = "全名"), edit = @Edit(title = "全名", type = EditType.INPUT, search = @Search, notNull = true, inputType = @InputType)) private String fullName; diff --git a/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/model/GithubTrendingRepo.java b/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/model/GithubTrendingRepo.java new file mode 100644 index 0000000..81bd4b0 --- /dev/null +++ b/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/model/GithubTrendingRepo.java @@ -0,0 +1,53 @@ +package io.fluent.github.model; + +import lombok.Data; +import xyz.erupt.annotation.Erupt; +import xyz.erupt.annotation.EruptField; +import xyz.erupt.annotation.sub_erupt.Layout; +import xyz.erupt.annotation.sub_erupt.Power; +import xyz.erupt.annotation.sub_field.Edit; +import xyz.erupt.annotation.sub_field.EditType; +import xyz.erupt.annotation.sub_field.View; +import xyz.erupt.annotation.sub_field.sub_edit.InputType; +import xyz.erupt.annotation.sub_field.sub_edit.Search; +import xyz.erupt.jpa.model.MetaModelVo; + +import javax.persistence.Entity; +import java.util.Date; + +@Data +@Entity +@Erupt(name = "Github Trending Repos", + power = @Power(importable = true, export = true), layout = @Layout( + tableLeftFixed = 3, + pageSize = 30)) +public class GithubTrendingRepo extends MetaModelVo { + @EruptField(views = @View(title = "名称"), edit = @Edit(title = "名称", type = EditType.INPUT, search = @Search, notNull = true, inputType = @InputType)) + private String name; + @EruptField(views = @View(title = "URL"), edit = @Edit(title = "URL", type = EditType.INPUT, search = @Search, notNull = true, inputType = @InputType)) + private String url; + @EruptField(views = @View(title = "全名"), edit = @Edit(title = "全名", type = EditType.INPUT, search = @Search, notNull = true, inputType = @InputType)) + private String fullName; + + private String nodeId; + @EruptField(views = @View(title = "描述"), edit = @Edit(title = "描述", type = EditType.INPUT, search = @Search, notNull = true, inputType = @InputType)) + private String description; + @EruptField(views = @View(title = "fork数量"), edit = @Edit(title = "fork数量", type = EditType.INPUT, search = @Search, notNull = true, inputType = @InputType)) + private int forksCount; + @EruptField(views = @View(title = "star数量"), edit = @Edit(title = "star数量", type = EditType.INPUT, search = @Search, notNull = true, inputType = @InputType)) + private int stargazersCount; + + + @EruptField(views = @View(title = "主题"), edit = @Edit(title = "主题", type = EditType.INPUT, search = @Search, notNull = true, inputType = @InputType)) + private String topics; + + @EruptField(views = @View(title = "语言"), edit = @Edit(title = "语言", type = EditType.INPUT, search = @Search, notNull = true, inputType = @InputType)) + private String language; + + + @EruptField(views = @View(title = "trendingDate"), edit = @Edit(title = "上榜日期", type = EditType.INPUT, search = @Search, notNull = true, inputType = @InputType)) + private Date trendingDate; + + @EruptField(views = @View(title = "周期"), edit = @Edit(title = "周期", type = EditType.INPUT, search = @Search, notNull = true, inputType = @InputType)) + private String dateRange; +} diff --git a/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/service/GithubService.java b/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/service/GithubService.java index c530d7f..348ff37 100644 --- a/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/service/GithubService.java +++ b/fluent-erupts/fleunt-github/src/main/java/io/fluent/github/service/GithubService.java @@ -14,4 +14,6 @@ public void saveUserStarredRepo(String userName,int page){ userService.saveUserStarredRepo(userName,page); log.info("complete saved user starred repo"); } + + } diff --git a/fluent-erupts/fluent-bpm/README.md b/fluent-erupts/fluent-bpm/README.md new file mode 100644 index 0000000..27f5612 --- /dev/null +++ b/fluent-erupts/fluent-bpm/README.md @@ -0,0 +1,12 @@ + +- 个人办公: 待办事项、抄送传阅、办理历史、发起申请、申请历史、我的草稿 + +- 内容管理: 公告、新闻 + +- 组织管理:组织管理、用户管理、角色管理、 岗位管理。笔者十多年研发见过无数组织架构,它堪称最精简最完美的设计。 + +- 流程管理: 表单表单设计、流程设计、流程实例管理、任务管理、系统对话框管理。(目前基于AgileBPM的商业组件,如果觉得不合适可切换为其他框架的流程模块,目前没有能入眼的) + +- 系统管理:字典分类管理、异常日志、系统资源、系统属性、常用脚本、短信邮件通知 + +- 资产管理 \ No newline at end of file diff --git a/modules/fluent-mocker/pom.xml b/fluent-erupts/fluent-bpm/pom.xml similarity index 57% rename from modules/fluent-mocker/pom.xml rename to fluent-erupts/fluent-bpm/pom.xml index c1fd962..e740d81 100644 --- a/modules/fluent-mocker/pom.xml +++ b/fluent-erupts/fluent-bpm/pom.xml @@ -5,12 +5,16 @@ 4.0.0 io.fluent - components + fluent-erupts 1.0-SNAPSHOT - fluent-mocker - + fluent-bpm + + 21 + 21 + UTF-8 + \ No newline at end of file diff --git a/fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/handlers/SqlTagFetchHandler.java b/fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/handlers/SqlTagFetchHandler.java similarity index 97% rename from fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/handlers/SqlTagFetchHandler.java rename to fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/handlers/SqlTagFetchHandler.java index 044f686..49c3f00 100644 --- a/fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/handlers/SqlTagFetchHandler.java +++ b/fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/handlers/SqlTagFetchHandler.java @@ -1,4 +1,4 @@ -package io.fluentqa.base.handlers; +package io.fluent.base.handlers; import java.util.List; import java.util.function.Supplier; diff --git a/fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/model/ModelWithValidFlag.java b/fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/model/ModelWithValidFlag.java similarity index 96% rename from fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/model/ModelWithValidFlag.java rename to fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/model/ModelWithValidFlag.java index 4f6e8b7..52d898e 100644 --- a/fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/model/ModelWithValidFlag.java +++ b/fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/model/ModelWithValidFlag.java @@ -1,4 +1,4 @@ -package io.fluentqa.base.model; +package io.fluent.base.model; import javax.persistence.MappedSuperclass; import xyz.erupt.annotation.EruptField; diff --git a/fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/model/ModelWithValidFlagVo.java b/fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/model/ModelWithValidFlagVo.java similarity index 97% rename from fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/model/ModelWithValidFlagVo.java rename to fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/model/ModelWithValidFlagVo.java index e93ded9..dcddd18 100644 --- a/fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/model/ModelWithValidFlagVo.java +++ b/fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/model/ModelWithValidFlagVo.java @@ -1,4 +1,4 @@ -package io.fluentqa.base.model; +package io.fluent.base.model; import javax.persistence.MappedSuperclass; import org.hibernate.annotations.DynamicInsert; diff --git a/fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/model/NamedModelVO.java b/fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/model/NamedModelVO.java similarity index 97% rename from fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/model/NamedModelVO.java rename to fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/model/NamedModelVO.java index 89e28ec..f92a302 100644 --- a/fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/model/NamedModelVO.java +++ b/fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/model/NamedModelVO.java @@ -1,4 +1,4 @@ -package io.fluentqa.base.model; +package io.fluent.base.model; import javax.persistence.MappedSuperclass; import org.hibernate.annotations.DynamicInsert; diff --git a/fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/model/NamedTimeStatusModel.java b/fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/model/NamedTimeStatusModel.java similarity index 98% rename from fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/model/NamedTimeStatusModel.java rename to fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/model/NamedTimeStatusModel.java index d29d492..fc6d038 100644 --- a/fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/model/NamedTimeStatusModel.java +++ b/fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/model/NamedTimeStatusModel.java @@ -1,4 +1,4 @@ -package io.fluentqa.base.model; +package io.fluent.base.model; import java.time.LocalDate; import javax.persistence.MappedSuperclass; diff --git a/fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/package-info.java b/fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/package-info.java new file mode 100644 index 0000000..f741592 --- /dev/null +++ b/fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/package-info.java @@ -0,0 +1 @@ +package io.fluent.base; diff --git a/fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/proxies/AuditDataEnhancerProxy.java b/fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/proxies/AuditDataEnhancerProxy.java similarity index 94% rename from fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/proxies/AuditDataEnhancerProxy.java rename to fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/proxies/AuditDataEnhancerProxy.java index 2ede92d..31ff66d 100644 --- a/fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/proxies/AuditDataEnhancerProxy.java +++ b/fluent-erupts/fluent-erupts-base/src/main/java/io/fluent/base/proxies/AuditDataEnhancerProxy.java @@ -1,4 +1,4 @@ -package io.fluentqa.base.proxies; +package io.fluent.base.proxies; import java.time.LocalDateTime; import org.springframework.stereotype.Component; diff --git a/fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/package-info.java b/fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/package-info.java deleted file mode 100644 index 3bce169..0000000 --- a/fluent-erupts/fluent-erupts-base/src/main/java/io/fluentqa/base/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package io.fluentqa.base; diff --git a/fluent-erupts/fluent-generator/src/main/java/io/fluentqa/generator/model/DataSourceModel.java b/fluent-erupts/fluent-generator/src/main/java/io/fluentqa/generator/model/DataSourceModel.java index 463c0b6..a30b72a 100644 --- a/fluent-erupts/fluent-generator/src/main/java/io/fluentqa/generator/model/DataSourceModel.java +++ b/fluent-erupts/fluent-generator/src/main/java/io/fluentqa/generator/model/DataSourceModel.java @@ -1,7 +1,7 @@ package io.fluentqa.generator.model; -import io.fluentqa.base.handlers.SqlTagFetchHandler; -import io.fluentqa.base.model.ModelWithValidFlagVo; +import io.fluent.base.handlers.SqlTagFetchHandler; +import io.fluent.base.model.ModelWithValidFlagVo; import io.fluentqa.generator.handlers.DataSourceTableSyncHandler; import org.hibernate.annotations.DynamicInsert; import org.hibernate.annotations.DynamicUpdate; diff --git a/fluent-erupts/fluent-generator/src/main/java/io/fluentqa/generator/model/DataSourceTableColumModel.java b/fluent-erupts/fluent-generator/src/main/java/io/fluentqa/generator/model/DataSourceTableColumModel.java index af89933..be40c77 100644 --- a/fluent-erupts/fluent-generator/src/main/java/io/fluentqa/generator/model/DataSourceTableColumModel.java +++ b/fluent-erupts/fluent-generator/src/main/java/io/fluentqa/generator/model/DataSourceTableColumModel.java @@ -1,7 +1,7 @@ package io.fluentqa.generator.model; -import io.fluentqa.base.handlers.SqlTagFetchHandler; -import io.fluentqa.base.model.ModelWithValidFlag; +import io.fluent.base.handlers.SqlTagFetchHandler; +import io.fluent.base.model.ModelWithValidFlag; import org.hibernate.annotations.DynamicInsert; import org.hibernate.annotations.DynamicUpdate; import org.hibernate.annotations.Where; diff --git a/fluent-erupts/fluent-generator/src/main/java/io/fluentqa/generator/model/SqlConfigEntity.java b/fluent-erupts/fluent-generator/src/main/java/io/fluentqa/generator/model/SqlConfigEntity.java index 39a0717..3f5d4c4 100644 --- a/fluent-erupts/fluent-generator/src/main/java/io/fluentqa/generator/model/SqlConfigEntity.java +++ b/fluent-erupts/fluent-generator/src/main/java/io/fluentqa/generator/model/SqlConfigEntity.java @@ -1,6 +1,6 @@ package io.fluentqa.generator.model; -import io.fluentqa.base.model.NamedModelVO; +import io.fluent.base.model.NamedModelVO; import lombok.Data; import org.hibernate.annotations.DynamicInsert; import org.hibernate.annotations.DynamicUpdate; diff --git a/fluent-erupts/pom.xml b/fluent-erupts/pom.xml index 66b425c..ccaf563 100644 --- a/fluent-erupts/pom.xml +++ b/fluent-erupts/pom.xml @@ -16,6 +16,7 @@ fluent-erupts-base fluent-generator fleunt-github + fluent-bpm diff --git a/fluent-wrappers/fluent-excel/src/main/java/io/fluentqa/excel/ExcelReadWriter.java b/fluent-wrappers/fluent-excel/src/main/java/io/fluent/excel/ExcelReadWriter.java similarity index 96% rename from fluent-wrappers/fluent-excel/src/main/java/io/fluentqa/excel/ExcelReadWriter.java rename to fluent-wrappers/fluent-excel/src/main/java/io/fluent/excel/ExcelReadWriter.java index 83765cf..40aa141 100644 --- a/fluent-wrappers/fluent-excel/src/main/java/io/fluentqa/excel/ExcelReadWriter.java +++ b/fluent-wrappers/fluent-excel/src/main/java/io/fluent/excel/ExcelReadWriter.java @@ -1,4 +1,4 @@ -package io.fluentqa.excel; +package io.fluent.excel; import com.github.crab2died.ExcelUtils; import com.github.crab2died.exceptions.Excel4JException; diff --git a/fluent-wrappers/fluent-excel/src/main/java/io/fluent/excel/package-info.java b/fluent-wrappers/fluent-excel/src/main/java/io/fluent/excel/package-info.java new file mode 100644 index 0000000..b27cea0 --- /dev/null +++ b/fluent-wrappers/fluent-excel/src/main/java/io/fluent/excel/package-info.java @@ -0,0 +1 @@ +package io.fluent.excel; diff --git a/fluent-wrappers/fluent-excel/src/main/java/io/fluentqa/excel/package-info.java b/fluent-wrappers/fluent-excel/src/main/java/io/fluentqa/excel/package-info.java deleted file mode 100644 index a033ad3..0000000 --- a/fluent-wrappers/fluent-excel/src/main/java/io/fluentqa/excel/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package io.fluentqa.excel; diff --git a/fluent-wrappers/fluent-excel/src/test/java/io/fluentqa/excel/DemoExcelModel.java b/fluent-wrappers/fluent-excel/src/test/java/io/fluent/excel/DemoExcelModel.java similarity index 92% rename from fluent-wrappers/fluent-excel/src/test/java/io/fluentqa/excel/DemoExcelModel.java rename to fluent-wrappers/fluent-excel/src/test/java/io/fluent/excel/DemoExcelModel.java index 0cbbcc5..87dbadb 100644 --- a/fluent-wrappers/fluent-excel/src/test/java/io/fluentqa/excel/DemoExcelModel.java +++ b/fluent-wrappers/fluent-excel/src/test/java/io/fluent/excel/DemoExcelModel.java @@ -1,4 +1,4 @@ -package io.fluentqa.excel; +package io.fluent.excel; import com.github.crab2died.annotation.ExcelField; import lombok.AllArgsConstructor; diff --git a/fluent-wrappers/fluent-excel/src/test/java/io/fluentqa/excel/ExcelUtilsTest.java b/fluent-wrappers/fluent-excel/src/test/java/io/fluent/excel/ExcelUtilsTest.java similarity index 96% rename from fluent-wrappers/fluent-excel/src/test/java/io/fluentqa/excel/ExcelUtilsTest.java rename to fluent-wrappers/fluent-excel/src/test/java/io/fluent/excel/ExcelUtilsTest.java index 1742770..3da3361 100644 --- a/fluent-wrappers/fluent-excel/src/test/java/io/fluentqa/excel/ExcelUtilsTest.java +++ b/fluent-wrappers/fluent-excel/src/test/java/io/fluent/excel/ExcelUtilsTest.java @@ -1,4 +1,4 @@ -package io.fluentqa.excel; +package io.fluent.excel; import java.io.File; import java.io.IOException; diff --git a/fluent-wrappers/fluent-git/pom.xml b/fluent-wrappers/fluent-git/pom.xml index 4d90fb4..3d13791 100644 --- a/fluent-wrappers/fluent-git/pom.xml +++ b/fluent-wrappers/fluent-git/pom.xml @@ -37,7 +37,11 @@ postgresql ${postgresql.version} - + + org.jsoup + jsoup + 1.17.2 + diff --git a/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/GithubUserService.java b/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/GithubUserService.java index e0ac806..84b8c87 100644 --- a/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/GithubUserService.java +++ b/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/GithubUserService.java @@ -1,14 +1,28 @@ package io.fluent.git.github; -import static io.fluent.git.github.config.ConfigHolder.getGithubApiClient; +import static io.fluent.git.github.config.ClientConfig.getGithubApiClient; +import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.jcabi.github.Github; import com.jcabi.http.response.JsonResponse; +import io.fluent.git.github.entity.GithubTrendingRepo; +import io.fluent.git.github.enums.GithubDateRange; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; +import java.util.ArrayList; + import io.fluent.git.github.models.GithubRepoModel; import io.fluent.git.github.repo.GithubDao; import java.io.IOException; import java.util.List; + + import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -49,7 +63,52 @@ private int saveIt(String userName, int page, int pageSize) .as(JsonResponse.class); List repos = JSONUtil.toList(result.body(), GithubRepoModel.class); + githubDao.saveAll(repos); return repos.size(); } + + public List getGithubTrendingRepos(String dateRange) { + + try { + String url = String.format("https://github.com/trending?since=%s", dateRange); + var client = new OkHttpClient(); + Request request = new Request.Builder() + .url(url) + .build(); + try (Response response = client.newCall(request).execute()) { + if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); + + Document doc = Jsoup.parse(response.body().string()); + Elements repoElements = doc.select("article.Box-row"); + + List trendingRepos = new ArrayList<>(); + for (Element repoElement : repoElements) { + String repoName = repoElement.selectXpath("h2").select("a").get(0).attr("href"); + String description = repoElement.select("p.col-9").text(); + String language = repoElement.select("span[itemprop=programmingLanguage]").text(); + String stars = repoElement.select("a.Link--muted").first().text(); + GithubTrendingRepo repo = new GithubTrendingRepo(); + repo.setFullName(repoName); + repo.setUrl(StrUtil.join("","https://github.com",repoName)); + repo.setDescription(description); + repo.setLanguages(language); + repo.setStargazersCount(Integer.parseInt(stars.replaceAll(",", ""))); + trendingRepos.add(repo); + } + + return trendingRepos; + } + } catch (IOException e) { + log.error("Error fetching trending repositories", e); + throw new RuntimeException("Failed to fetch trending repositories", e); + } + } + + public void saveGithubTrendingRepo(){ + for (GithubDateRange value : GithubDateRange.values()) { + List models = getGithubTrendingRepos(value.toString()); + System.out.println(models); + } + } } diff --git a/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/config/ConfigHolder.java b/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/config/ClientConfig.java similarity index 96% rename from fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/config/ConfigHolder.java rename to fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/config/ClientConfig.java index f3a90d8..0ffd95a 100644 --- a/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/config/ConfigHolder.java +++ b/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/config/ClientConfig.java @@ -6,7 +6,7 @@ import io.fluent.quickdao.datasource.model.DataSourceSetting; import io.github.cdimascio.dotenv.Dotenv; -public class ConfigHolder { +public class ClientConfig { public static Dotenv dotenv = Dotenv.load(); diff --git a/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/entity/GithubStarredRepo.java b/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/entity/GithubStarredRepo.java index 769b240..0d460f8 100644 --- a/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/entity/GithubStarredRepo.java +++ b/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/entity/GithubStarredRepo.java @@ -8,6 +8,8 @@ public class GithubStarredRepo { private Long id; private String name; private String url; + @QuickDaoColumn(name = "html_url") + private String htmlUrl; @QuickDaoColumn(name = "full_name") private String fullName; diff --git a/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/entity/GithubTrendingRepo.java b/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/entity/GithubTrendingRepo.java new file mode 100644 index 0000000..bc0ef45 --- /dev/null +++ b/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/entity/GithubTrendingRepo.java @@ -0,0 +1,43 @@ +package io.fluent.git.github.entity; + +import io.fluent.git.github.models.GithubRepoModel; +import io.fluent.quickdao.annotations.QuickDaoColumn; +import lombok.Data; + +import java.util.Date; + +@Data +public class GithubTrendingRepo { + private Long id; + @QuickDaoColumn(name = "name") + private String name; + @QuickDaoColumn(name = "trending_date") + private String url; + @QuickDaoColumn(name = "full_name") + private String fullName; + + @QuickDaoColumn(name = "node_id") + private String nodeId; + @QuickDaoColumn(name = "description") + private String description; + + @QuickDaoColumn(name = "forks_count") + private int forksCount; + + @QuickDaoColumn(name = "stargazers_count") + private int stargazersCount; + + @QuickDaoColumn(name = "topics") + private String topics; + + @QuickDaoColumn(name = "languages") + private String languages; + + @QuickDaoColumn(name = "date_range") + private String dateRange; + + @QuickDaoColumn(name = "trending_date") + private Date trendingDate; + + +} diff --git a/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/enums/GithubDateRange.java b/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/enums/GithubDateRange.java new file mode 100644 index 0000000..88e16d4 --- /dev/null +++ b/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/enums/GithubDateRange.java @@ -0,0 +1,5 @@ +package io.fluent.git.github.enums; + +public enum GithubDateRange { + Daily,Weekly,Monthly +} diff --git a/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/repo/GithubDao.java b/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/repo/GithubDao.java index 143936a..3717c62 100644 --- a/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/repo/GithubDao.java +++ b/fluent-wrappers/fluent-git/src/main/java/io/fluent/git/github/repo/GithubDao.java @@ -2,28 +2,47 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.StrUtil; -import io.fluent.git.github.config.ConfigHolder; +import io.fluent.git.github.config.ClientConfig; import io.fluent.git.github.entity.GithubStarredRepo; +import io.fluent.git.github.entity.GithubTrendingRepo; import io.fluent.git.github.models.GithubRepoModel; import io.fluent.quickdao.QuickDao; + +import java.util.Date; import java.util.List; + import lombok.extern.slf4j.Slf4j; @Slf4j public class GithubDao { - private QuickDao dao = ConfigHolder.getDao(); + private QuickDao dao = ClientConfig.getDao(); - public void save(GithubRepoModel model) { - GithubStarredRepo entity = BeanUtil.copyProperties(model, GithubStarredRepo.class, "topics"); + public void saveGithubStarredRepo(GithubRepoModel model) { + GithubStarredRepo entity = BeanUtil.copyProperties(model, GithubStarredRepo.class, "topics"); - entity.setTopics(StrUtil.join(",", model.getTopics())); - dao.saveOrUpdate(entity, "github_starred_repo", "node_id"); - } + entity.setTopics(StrUtil.join(",", model.getTopics())); + dao.saveOrUpdate(entity, "github_starred_repo", "node_id"); + } + + public void saveGithubTrendingRepo(GithubTrendingRepo model) { + dao.saveOrUpdate(model, "github_trending_repo", "name"); + } - public void saveAll(List models) { - for (GithubRepoModel model : models) { - log.info("start save model : {}", model.getFullName()); - save(model); + public void saveAllGithubTrendingRepo(List models) { + var today = new Date(); + for (GithubTrendingRepo model : models) { + log.info("start save model : {}", model.getFullName()); + model.setTrendingDate(today); + saveGithubTrendingRepo(model); + } } - } + + public void saveAll(List models) { + for (GithubRepoModel model : models) { + log.info("start save model : {}", model.getFullName()); + saveGithubStarredRepo(model); + } + } + + } diff --git a/fluent-wrappers/fluent-git/src/test/java/io/fluent/git/github/GithubUserServiceTest.java b/fluent-wrappers/fluent-git/src/test/java/io/fluent/git/github/GithubUserServiceTest.java index ce57529..12e0ab1 100644 --- a/fluent-wrappers/fluent-git/src/test/java/io/fluent/git/github/GithubUserServiceTest.java +++ b/fluent-wrappers/fluent-git/src/test/java/io/fluent/git/github/GithubUserServiceTest.java @@ -4,6 +4,7 @@ import com.jcabi.github.Github; import com.jcabi.github.RtGithub; import com.jcabi.http.response.JsonResponse; +import io.fluent.git.github.enums.GithubDateRange; import io.fluent.git.github.models.GithubRepoModel; import io.github.cdimascio.dotenv.Dotenv; import java.io.IOException; @@ -16,6 +17,7 @@ public class GithubUserServiceTest { String githubAccessToken = dotenv.get("GITHUB_ACCESS_TOKEN"); Github github = new RtGithub(githubAccessToken); + GithubUserService service = new GithubUserService(); @Test public void createGithubClient() throws IOException { @@ -48,4 +50,10 @@ public void testSaveGithubRepos() { GithubUserService service = new GithubUserService(); service.saveUserStarredRepo("kennethreitz", 0); } + + @Test + public void testGetGithubTrendingRepos() { + var result = service.getGithubTrendingRepos(GithubDateRange.Daily.toString()); + System.out.println(result); + } } diff --git a/fluent-wrappers/fluent-httpclients/src/main/java/io/fluent/clients/base/HttpLogger.java b/fluent-wrappers/fluent-httpclients/src/main/java/io/fluent/clients/base/HttpLogger.java new file mode 100644 index 0000000..d2c4835 --- /dev/null +++ b/fluent-wrappers/fluent-httpclients/src/main/java/io/fluent/clients/base/HttpLogger.java @@ -0,0 +1,41 @@ +package io.fluent.clients.base; + +import cn.hutool.core.util.StrUtil; +import okhttp3.logging.HttpLoggingInterceptor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.Marker; +import org.slf4j.MarkerFactory; + +public class HttpLogger implements HttpLoggingInterceptor.Logger { + private static final Marker MARKER = MarkerFactory.getMarker("OKHTTP"); + + private final Logger logger; + + public HttpLogger() { + this.logger = LoggerFactory.getLogger(HttpLogger.class); + } + + public HttpLogger(Logger logger) { + if (logger != null) { + this.logger = logger; + } else { + this.logger = LoggerFactory.getLogger(HttpLogger.class); + } + } + + public HttpLogger(String logName) { + + if (StrUtil.isBlank(logName)) { + this.logger = LoggerFactory.getLogger(HttpLogger.class); + } else { + this.logger = LoggerFactory.getLogger(logName); + } + } + + @Override + public void log(String message) { + + logger.debug(MARKER, message); + } +} \ No newline at end of file diff --git a/fluent-wrappers/fluent-httpclients/src/main/java/io/fluent/clients/base/HttpRequestModel.java b/fluent-wrappers/fluent-httpclients/src/main/java/io/fluent/clients/base/HttpRequestModel.java index 4129a34..fcb66e1 100644 --- a/fluent-wrappers/fluent-httpclients/src/main/java/io/fluent/clients/base/HttpRequestModel.java +++ b/fluent-wrappers/fluent-httpclients/src/main/java/io/fluent/clients/base/HttpRequestModel.java @@ -47,6 +47,16 @@ public HttpRequestModel addQueryParams(String key, String value) { return this; } + public HttpRequestModel baseUrl(String baseUrl) { + this.baseUrl = baseUrl; + return this; + } + + public HttpRequestModel urlPath(String urlPath) { + this.urlPath = urlPath; + return this; + } + public HttpRequestModel addHeader(String key, String value) { this.headers.put(key, value); return this; diff --git a/fluent-wrappers/fluent-httpclients/src/main/java/io/fluent/clients/factory/HttpClientFactory.java b/fluent-wrappers/fluent-httpclients/src/main/java/io/fluent/clients/factory/HttpClientFactory.java index a05f28d..419d90e 100644 --- a/fluent-wrappers/fluent-httpclients/src/main/java/io/fluent/clients/factory/HttpClientFactory.java +++ b/fluent-wrappers/fluent-httpclients/src/main/java/io/fluent/clients/factory/HttpClientFactory.java @@ -3,11 +3,13 @@ import static java.net.CookiePolicy.ACCEPT_ORIGINAL_SERVER; import io.fluent.clients.base.HttpClientOption; + import java.net.CookieManager; import java.net.InetSocketAddress; import java.net.Proxy; import java.time.Duration; import java.util.concurrent.TimeUnit; + import okhttp3.ConnectionPool; import okhttp3.Credentials; import okhttp3.JavaNetCookieJar; @@ -16,48 +18,48 @@ public class HttpClientFactory { - public OkHttpClient okHttpClient(HttpClientOption httpConfig) { - - ConnectionPool connectionPool = - new ConnectionPool( - httpConfig.getMaxIdleConnections(), - httpConfig.getKeepAliveDuration(), - TimeUnit.SECONDS); - - OkHttpClient.Builder builder = - new OkHttpClient.Builder() - .connectionPool(connectionPool) - // 跳转由自己控制 - .followRedirects(false) - .readTimeout(Duration.ofSeconds(httpConfig.getReadTimeout())) - .connectTimeout(Duration.ofSeconds(httpConfig.getReadTimeout())); - - if (httpConfig.isCookie()) { - CookieManager cookieManager = new CookieManager(null, ACCEPT_ORIGINAL_SERVER); - builder.cookieJar(new JavaNetCookieJar(cookieManager)); - } - // proxy - if (httpConfig.isUseProxy()) { - builder.proxy( - new Proxy( - httpConfig.getProxy().getType(), - new InetSocketAddress( - httpConfig.getProxy().getHost(), httpConfig.getProxy().getPort()))); - if (StringUtils.isNotBlank(httpConfig.getProxy().getPassword())) { - builder.proxyAuthenticator( - (route, response) -> { - // 设置代理服务器账号密码 - String credential = - Credentials.basic( - httpConfig.getProxy().getUserName(), httpConfig.getProxy().getPassword()); - return response - .request() - .newBuilder() - .header("Proxy-Authorization", credential) - .build(); - }); - } + public OkHttpClient okHttpClient(HttpClientOption httpConfig) { + + ConnectionPool connectionPool = + new ConnectionPool( + httpConfig.getMaxIdleConnections(), + httpConfig.getKeepAliveDuration(), + TimeUnit.SECONDS); + + OkHttpClient.Builder builder = + new OkHttpClient.Builder() + .connectionPool(connectionPool) + // 跳转由自己控制 + .followRedirects(false) + .readTimeout(Duration.ofSeconds(httpConfig.getReadTimeout())) + .connectTimeout(Duration.ofSeconds(httpConfig.getReadTimeout())); + + if (httpConfig.isCookie()) { + CookieManager cookieManager = new CookieManager(null, ACCEPT_ORIGINAL_SERVER); + builder.cookieJar(new JavaNetCookieJar(cookieManager)); + } + // proxy + if (httpConfig.isUseProxy()) { + builder.proxy( + new Proxy( + httpConfig.getProxy().getType(), + new InetSocketAddress( + httpConfig.getProxy().getHost(), httpConfig.getProxy().getPort()))); + if (StringUtils.isNotBlank(httpConfig.getProxy().getPassword())) { + builder.proxyAuthenticator( + (route, response) -> { + // 设置代理服务器账号密码 + String credential = + Credentials.basic( + httpConfig.getProxy().getUserName(), httpConfig.getProxy().getPassword()); + return response + .request() + .newBuilder() + .header("Proxy-Authorization", credential) + .build(); + }); + } + } + return builder.build(); } - return builder.build(); - } } diff --git a/fluent-wrappers/fluent-httpclients/src/main/java/io/fluent/clients/factory/HttpClientProcessor.java b/fluent-wrappers/fluent-httpclients/src/main/java/io/fluent/clients/factory/HttpClientProcessor.java index 5713a3d..fe9a7be 100644 --- a/fluent-wrappers/fluent-httpclients/src/main/java/io/fluent/clients/factory/HttpClientProcessor.java +++ b/fluent-wrappers/fluent-httpclients/src/main/java/io/fluent/clients/factory/HttpClientProcessor.java @@ -1,11 +1,19 @@ package io.fluent.clients.factory; import io.fluent.clients.base.HttpClientOption; +import io.fluent.clients.base.HttpException; import io.fluent.clients.base.HttpRequestModel; import java.io.IOException; + +import okhttp3.Call; import okhttp3.OkHttpClient; import okhttp3.Response; +/** + * 1. setup processor + * 2. send request model + * 3. get response then handle response + */ public class HttpClientProcessor { private HttpClientOption httpClientConfig; @@ -29,4 +37,9 @@ public Response invoke(HttpRequestModel httpRequestModel) { } return response; } + //TODO: implement async invoke + public Response asyncInvoke(HttpRequestModel httpRequestModel) { + + throw new RuntimeException("Not implemented"); + } } diff --git a/fluent-wrappers/fluent-httpclients/src/test/java/io/fluent/clients/factory/HttpClientFactoryTest.java b/fluent-wrappers/fluent-httpclients/src/test/java/io/fluent/clients/factory/HttpClientFactoryTest.java index df97f58..37213da 100644 --- a/fluent-wrappers/fluent-httpclients/src/test/java/io/fluent/clients/factory/HttpClientFactoryTest.java +++ b/fluent-wrappers/fluent-httpclients/src/test/java/io/fluent/clients/factory/HttpClientFactoryTest.java @@ -1,144 +1,146 @@ -// package io.fluentqa.clients.factory; +//package io.fluent.clients.factory; // -// import io.fluentqa.builtin.jsons.JSONUtils; -// import io.fluentqa.clients.base.HttpClientOption; -// import io.fluentqa.clients.base.HttpRequestModel; -// import okhttp3.OkHttpClient; -// import okhttp3.Request; -// import okhttp3.RequestBody; -// import okhttp3.Response; -// import org.junit.jupiter.api.Test; +//import cn.hutool.json.JSONUtil; +//import io.fluent.clients.base.HttpClientOption; +//import io.fluent.clients.base.HttpRequestModel; +//import okhttp3.OkHttpClient; +//import okhttp3.Request; +//import okhttp3.RequestBody; +//import okhttp3.Response; +//import org.junit.jupiter.api.Test; // -// import java.io.IOException; -// import java.nio.charset.StandardCharsets; +//import java.io.IOException; +//import java.nio.charset.StandardCharsets; // -// import static org.junit.jupiter.api.Assertions.*; +//import static org.junit.jupiter.api.Assertions.*; // -// public class HttpClientFactoryTest { -// HttpClientFactory factory = new HttpClientFactory(); -// HttpClientOption config = new HttpClientOption(); -// OkHttpClient client = factory.okHttpClient(config); // -// @Test -// void test_OkHttpClient() { +//public class HttpClientFactoryTest { +// HttpClientFactory factory = new HttpClientFactory(); +// HttpClientOption config = new HttpClientOption(); // OkHttpClient client = factory.okHttpClient(config); -// assertNotNull(client); -// } -// -// @Test -// void test_OkHttpClient_get() { -// Request request = new Request.Builder() -// .url("https://www.baidu.com").build(); -// callApi(request); -// } -// -// String tokenRespones = "{\"user_info\":{\"id\":1,\"name\":\"prest\",\"username\":\"prest\"," + -// "\"metadata\":null},\"token\":" + -// -// "\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySW5mbyI6eyJpZCI6MSwibWV0YWRhdGEiOm51bGwsIm5hbWUiOiJwcmVzdCIsInVzZXJuYW1lIjoicHJlc3QifSwiZXhwIjoxNjgzNTY2MTMzLCJuYmYiOjE2ODM1NDQ1MzN9.4xSD5TiEnauLrLwLRbEHxwK6lduXIjvwijiPLXvYdYo\"}\n"; -// -// @Test -// void testPrestdGetSchema() { -// Request request = new Request.Builder().url("http://127.0.0.1:3000/auth") -// .post(RequestBody.create("{\"username\": \"prest\", \"password\": \"prest\"}" -// .getBytes(StandardCharsets.UTF_8))).build(); -// Response response = null; -// callApi(request); -// } -// -// private void callApi(Request request) { -// Response response; -// try { -// response = client.newCall(request).execute(); -// System.out.println(response.body().string()); -// } catch (IOException e) { -// throw new RuntimeException(e); +// +// @Test +// void test_OkHttpClient() { +// OkHttpClient client = factory.okHttpClient(config); +// assertNotNull(client); +// } +// +// @Test +// void test_OkHttpClient_get() { +// Request request = new Request.Builder() +// .url("https://www.baidu.com").build(); +// callApi(request); +// } +// +// String tokenRespones = "{\"user_info\":{\"id\":1,\"name\":\"prest\",\"username\":\"prest\"," + +// "\"metadata\":null},\"token\":" + +// +// "\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySW5mbyI6eyJpZCI6MSwibWV0YWRhdGEiOm51bGwsIm5hbWUiOiJwcmVzdCIsInVzZXJuYW1lIjoicHJlc3QifSwiZXhwIjoxNjgzNTY2MTMzLCJuYmYiOjE2ODM1NDQ1MzN9.4xSD5TiEnauLrLwLRbEHxwK6lduXIjvwijiPLXvYdYo\"}\n"; +// +// @Test +// void testPrestdGetSchema() { +// Request request = new Request.Builder().url("http://127.0.0.1:3000/auth") +// .post(RequestBody.create("{\"username\": \"prest\", \"password\": \"prest\"}" +// .getBytes(StandardCharsets.UTF_8))).build(); +// Response response = null; +// callApi(request); +// } +// +// private void callApi(Request request) { +// Response response; +// try { +// response = client.newCall(request).execute(); +// System.out.println(response.body().string()); +// } catch (IOException e) { +// throw new RuntimeException(e); +// } +// } +// +// String baseUrl = "http://127.0.0.1:3000"; +// //Authorization: Bearer {TOKEN} +// String auth = "auth"; +// String show_url = "/show/{DATABASE}/{SCHEMA}/{TABLE}"; +// +// /** +// * Endpoints Description +// * /_health Health check endpoint +// * /databases List all databases +// * /schemas List all schemas +// * /tables List all tables +// * /show/{DATABASE}/{SCHEMA}/{TABLE} Lists table structure - all fields contained in the table +// * /{DATABASE}/{SCHEMA} Lists table tables - find by schema +// * /{DATABASE}/{SCHEMA}/{TABLE} List all rows, find by database, schema and table +// * /{DATABASE}/{SCHEMA}/{VIEW} List all rows, find by database, schema and view +// *

+// * POST: +// * /{DATABASE}/{SCHEMA}/{TABLE} +// * { +// * "FIELD1": "string value", +// * "FIELD2": 1234567890 +// * } +// *

+// * PATCH/PUT: +// * /{DATABASE}/{SCHEMA}/{TABLE}?{FIELD NAME}={VALUE} +// * { +// * "FIELD1": "string value", +// * "FIELD2": 1234567890, +// * "ARRAYFIELD": ["value 1","value 2"] +// * } +// * DELETE: +// * /{DATABASE}/{SCHEMA}/{TABLE}?{FIELD NAME}={VALUE} +// */ +// @Test +// void testprestdGetDatabases() { +// prestdQueryService("databases"); +// prestdQueryService("schemas"); +// prestdQueryService("tables"); +// } +// +// void prestdQueryService(String serviceName) { +// String token = JSONUtil.parse(tokenRespones).getByPath("token").toString(); +// Request request = new Request.Builder().url("http://127.0.0.1:3000/" + serviceName) +// .addHeader("Authorization", "Bearer %s".formatted(token)) +// .get().build(); +// callApi(request); +// } +// +// //supabase postrest invocation +// @Test +// void querySupabaseService() { +// String baseUrl = "http://localhost:54321/rest/v1/users"; +// String serviceKey +// = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU"; +// String apiKey +// = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0"; +// Request request = new Request.Builder().url(baseUrl) +// .addHeader("Authorization", "Bearer %s".formatted(serviceKey)) +// .addHeader("apikey", apiKey) +// .get().build(); +// callApi(request); +// } +// +// @Test +// void functionCall() { +// String baseUrl = +// "http://localhost:54321/rest/v1/rpc/get_key_by_email?in_email=test_1@163.com"; +// String serviceKey +// = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU"; +// String apiKey +// = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0"; +// Request request = new Request.Builder().url(baseUrl) +// .addHeader("Authorization", "Bearer %s".formatted(serviceKey)) +// .addHeader("apikey", apiKey) +// .get().build(); +// callApi(request); +// } +// +// @Test +// void testHttpProcessor() { +// HttpRequestModel request = new HttpRequestModel(); +// HttpClientProcessor processor = new HttpClientProcessor(); +// processor.init(); +// processor.invoke(request); +// // } -// } -// -// String baseUrl = "http://127.0.0.1:3000"; -// //Authorization: Bearer {TOKEN} -// String auth="auth"; -// String show_url="/show/{DATABASE}/{SCHEMA}/{TABLE}"; -// -// /** -// * Endpoints Description -// * /_health Health check endpoint -// * /databases List all databases -// * /schemas List all schemas -// * /tables List all tables -// * /show/{DATABASE}/{SCHEMA}/{TABLE} Lists table structure - all fields contained in the table -// * /{DATABASE}/{SCHEMA} Lists table tables - find by schema -// * /{DATABASE}/{SCHEMA}/{TABLE} List all rows, find by database, schema and table -// * /{DATABASE}/{SCHEMA}/{VIEW} List all rows, find by database, schema and view -// * -// * POST: -// * /{DATABASE}/{SCHEMA}/{TABLE} -// * { -// * "FIELD1": "string value", -// * "FIELD2": 1234567890 -// * } -// * -// * PATCH/PUT: -// * /{DATABASE}/{SCHEMA}/{TABLE}?{FIELD NAME}={VALUE} -// * { -// * "FIELD1": "string value", -// * "FIELD2": 1234567890, -// * "ARRAYFIELD": ["value 1","value 2"] -// * } -// * DELETE: -// * /{DATABASE}/{SCHEMA}/{TABLE}?{FIELD NAME}={VALUE} -// */ -// @Test -// void testprestdGetDatabases() { -// prestdQueryService("databases"); -// prestdQueryService("schemas"); -// prestdQueryService("tables"); -// } -// -// void prestdQueryService(String serviceName){ -// String token = JSONUtils.parse(tokenRespones).getByPath("token").toString(); -// Request request = new Request.Builder().url("http://127.0.0.1:3000/"+serviceName) -// .addHeader("Authorization", "Bearer %s".formatted(token)) -// .get().build(); -// callApi(request); -// } -// //supabase postrest invocation -// @Test -// void querySupabaseService(){ -// String baseUrl = "http://localhost:54321/rest/v1/users"; -// String serviceKey -// ="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU"; -// String apiKey -// ="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0"; -// Request request = new Request.Builder().url(baseUrl) -// .addHeader("Authorization", "Bearer %s".formatted(serviceKey)) -// .addHeader("apikey", apiKey) -// .get().build(); -// callApi(request); -// } -// -// @Test -// void functionCall(){ -// String baseUrl = -// "http://localhost:54321/rest/v1/rpc/get_key_by_email?in_email=test_1@163.com"; -// String serviceKey -// ="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU"; -// String apiKey -// ="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0"; -// Request request = new Request.Builder().url(baseUrl) -// .addHeader("Authorization", "Bearer %s".formatted(serviceKey)) -// .addHeader("apikey", apiKey) -// .get().build(); -// callApi(request); -// } -// -// @Test -// void testHttpProcessor(){ -// HttpRequestModel request = new HttpRequestModel(); -// HttpClientProcessor processor = new HttpClientProcessor(); -// processor.init(); -// processor.invoke(request); -// -// } -// } +//} diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/BasicAuthentication.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/BasicAuthentication.java similarity index 91% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/BasicAuthentication.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/BasicAuthentication.java index d41aa52..d8d2eeb 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/BasicAuthentication.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/BasicAuthentication.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.config; +package io.fluent.jira.config; public class BasicAuthentication { diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/CacheConfig.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/CacheConfig.java similarity index 93% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/CacheConfig.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/CacheConfig.java index 47ff8ab..c28ac13 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/CacheConfig.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/CacheConfig.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.config; +package io.fluent.jira.config; public class CacheConfig { diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/CommentMappingConfig.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/CommentMappingConfig.java similarity index 97% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/CommentMappingConfig.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/CommentMappingConfig.java index 4c77242..182e487 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/CommentMappingConfig.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/CommentMappingConfig.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.config; +package io.fluent.jira.config; public class CommentMappingConfig { diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/Context.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/Context.java similarity index 57% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/Context.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/Context.java index e5b8292..e07e14d 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/Context.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/Context.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.config; +package io.fluent.jira.config; public enum Context { SOURCE, diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/DescriptionMappingConfig.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/DescriptionMappingConfig.java similarity index 94% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/DescriptionMappingConfig.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/DescriptionMappingConfig.java index 51e30eb..247ae3e 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/DescriptionMappingConfig.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/DescriptionMappingConfig.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.config; +package io.fluent.jira.config; public class DescriptionMappingConfig { diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/JiraConnectionProperties.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/JiraConnectionProperties.java similarity index 97% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/JiraConnectionProperties.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/JiraConnectionProperties.java index ce0c4bc..aee16fb 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/JiraConnectionProperties.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/JiraConnectionProperties.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.config; +package io.fluent.jira.config; import java.io.File; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/JiraProjectSync.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/JiraProjectSync.java similarity index 99% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/JiraProjectSync.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/JiraProjectSync.java index cfaa299..d57b459 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/JiraProjectSync.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/JiraProjectSync.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.config; +package io.fluent.jira.config; import java.net.URL; import java.util.Arrays; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/JiraSyncConfig.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/JiraSyncConfig.java similarity index 97% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/JiraSyncConfig.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/JiraSyncConfig.java index bf6841c..1503031 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/JiraSyncConfig.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/JiraSyncConfig.java @@ -1,6 +1,7 @@ -package io.fluentqa.jira.config; +package io.fluent.jira.config; + +import io.fluent.jira.domain.JiraProject; -import io.fluentqa.jira.domain.JiraProject; import java.util.LinkedHashMap; import java.util.Map; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/TransitionConfig.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/TransitionConfig.java similarity index 96% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/TransitionConfig.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/TransitionConfig.java index 91c8271..ad98666 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/config/TransitionConfig.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/config/TransitionConfig.java @@ -1,7 +1,7 @@ -package io.fluentqa.jira.config; +package io.fluent.jira.config; -import io.fluentqa.jira.domain.JiraIssue; -import io.fluentqa.jira.domain.JiraIssueType; +import io.fluent.jira.domain.JiraIssue; +import io.fluent.jira.domain.JiraIssueType; import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedHashSet; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraChangeLog.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraChangeLog.java similarity index 97% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraChangeLog.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraChangeLog.java index f6dd3c7..706a9b1 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraChangeLog.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraChangeLog.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import com.fasterxml.jackson.annotation.JsonIgnore; import java.io.Serializable; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraComment.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraComment.java similarity index 86% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraComment.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraComment.java index 17c5e0b..4757e94 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraComment.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraComment.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import com.fasterxml.jackson.annotation.JsonFormat; import java.time.ZonedDateTime; @@ -11,10 +11,10 @@ public class JiraComment extends JiraIdResource { private String body; - @JsonFormat(pattern = JiraResource.JIRA_DATE_FORMAT) + @JsonFormat(pattern = JIRA_DATE_FORMAT) private ZonedDateTime created; - @JsonFormat(pattern = JiraResource.JIRA_DATE_FORMAT) + @JsonFormat(pattern = JIRA_DATE_FORMAT) private ZonedDateTime updated; public JiraComment() {} diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraComments.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraComments.java similarity index 96% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraComments.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraComments.java index 1f9cb07..c047fcd 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraComments.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraComments.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.io.Serializable; import java.util.ArrayList; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraComponent.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraComponent.java similarity index 86% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraComponent.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraComponent.java index 71a9174..89dcad2 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraComponent.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraComponent.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; public class JiraComponent extends JiraNamedResource { diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraComponentsList.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraComponentsList.java similarity index 82% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraComponentsList.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraComponentsList.java index 53549ac..e3d84be 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraComponentsList.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraComponentsList.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.util.ArrayList; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraField.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraField.java similarity index 94% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraField.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraField.java index f0d772c..a7016ac 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraField.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraField.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; public class JiraField extends JiraNamedResource { diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraFieldList.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraFieldList.java similarity index 85% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraFieldList.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraFieldList.java index 5ec98a4..12826c0 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraFieldList.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraFieldList.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.io.Serializable; import java.util.ArrayList; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraFieldSchema.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraFieldSchema.java similarity index 95% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraFieldSchema.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraFieldSchema.java index 4abe18e..ac6a3da 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraFieldSchema.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraFieldSchema.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.io.Serializable; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraFieldsBean.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraFieldsBean.java similarity index 94% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraFieldsBean.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraFieldsBean.java index 171dd90..c5a7137 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraFieldsBean.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraFieldsBean.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.util.Set; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraFieldsUpdate.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraFieldsUpdate.java similarity index 98% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraFieldsUpdate.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraFieldsUpdate.java index 6326d23..c1c73f3 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraFieldsUpdate.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraFieldsUpdate.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraFilterResult.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraFilterResult.java similarity index 89% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraFilterResult.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraFilterResult.java index 3272532..6a415c3 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraFilterResult.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraFilterResult.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.io.Serializable; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIdResource.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIdResource.java similarity index 91% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIdResource.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIdResource.java index a6a33e8..4ef4f82 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIdResource.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIdResource.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; public abstract class JiraIdResource extends JiraResource { diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssue.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssue.java similarity index 97% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssue.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssue.java index 2a95a3e..408989d 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssue.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssue.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import com.fasterxml.jackson.annotation.JsonIgnore; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssueFields.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssueFields.java similarity index 99% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssueFields.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssueFields.java index 4df5048..ffcd374 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssueFields.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssueFields.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssueHistoryEntry.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssueHistoryEntry.java similarity index 97% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssueHistoryEntry.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssueHistoryEntry.java index 7196b51..74ee3f8 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssueHistoryEntry.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssueHistoryEntry.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssueHistoryItem.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssueHistoryItem.java similarity index 98% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssueHistoryItem.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssueHistoryItem.java index 9d6c32b..a91d1d6 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssueHistoryItem.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssueHistoryItem.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import com.fasterxml.jackson.annotation.JsonIgnore; import java.io.Serializable; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssueStatus.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssueStatus.java similarity index 86% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssueStatus.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssueStatus.java index cbe49d7..b3c058c 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssueStatus.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssueStatus.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; public class JiraIssueStatus extends JiraNamedResource { diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssueType.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssueType.java similarity index 86% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssueType.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssueType.java index a4d4c9c..b116c0e 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssueType.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssueType.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; public class JiraIssueType extends JiraNamedResource { diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssueUpdate.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssueUpdate.java similarity index 97% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssueUpdate.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssueUpdate.java index ba10c05..1846d78 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraIssueUpdate.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraIssueUpdate.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import com.fasterxml.jackson.annotation.JsonIgnore; import java.io.Serializable; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraLinkIcon.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraLinkIcon.java similarity index 92% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraLinkIcon.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraLinkIcon.java index 2c2f9f0..5c48b13 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraLinkIcon.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraLinkIcon.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.io.Serializable; import java.net.URL; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraLoginRequest.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraLoginRequest.java similarity index 95% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraLoginRequest.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraLoginRequest.java index ce330c9..6a101f8 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraLoginRequest.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraLoginRequest.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.io.Serializable; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraLoginResponse.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraLoginResponse.java similarity index 90% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraLoginResponse.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraLoginResponse.java index 1e1676e..333ded5 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraLoginResponse.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraLoginResponse.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.io.Serializable; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraNamedBean.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraNamedBean.java similarity index 84% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraNamedBean.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraNamedBean.java index 679ccec..b92e45f 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraNamedBean.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraNamedBean.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; public interface JiraNamedBean { diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraNamedResource.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraNamedResource.java similarity index 93% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraNamedResource.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraNamedResource.java index 2ab329e..b8a0ef7 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraNamedResource.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraNamedResource.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.util.Objects; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraPriority.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraPriority.java similarity index 86% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraPriority.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraPriority.java index db412cb..93a1027 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraPriority.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraPriority.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; public class JiraPriority extends JiraNamedResource { diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraPriorityList.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraPriorityList.java similarity index 85% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraPriorityList.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraPriorityList.java index b652794..84bb255 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraPriorityList.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraPriorityList.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.io.Serializable; import java.util.ArrayList; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraProject.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraProject.java similarity index 96% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraProject.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraProject.java index 44ef64f..1f57ddd 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraProject.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraProject.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.util.List; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraProjectsList.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraProjectsList.java similarity index 81% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraProjectsList.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraProjectsList.java index dba3939..76f6aa1 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraProjectsList.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraProjectsList.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.util.ArrayList; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraRemoteLink.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraRemoteLink.java similarity index 95% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraRemoteLink.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraRemoteLink.java index b6f674f..bc9c9a5 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraRemoteLink.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraRemoteLink.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.net.MalformedURLException; import java.net.URL; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraRemoteLinkObject.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraRemoteLinkObject.java similarity index 95% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraRemoteLinkObject.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraRemoteLinkObject.java index c0bd5cc..eab71d9 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraRemoteLinkObject.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraRemoteLinkObject.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.io.Serializable; import java.net.URL; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraRemoteLinks.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraRemoteLinks.java similarity index 85% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraRemoteLinks.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraRemoteLinks.java index 8cce824..d809f9b 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraRemoteLinks.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraRemoteLinks.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.io.Serializable; import java.util.ArrayList; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraResolution.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraResolution.java similarity index 86% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraResolution.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraResolution.java index 5868dd7..27b7823 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraResolution.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraResolution.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; public class JiraResolution extends JiraNamedResource { diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraResolutionList.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraResolutionList.java similarity index 86% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraResolutionList.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraResolutionList.java index 3d7d404..b4997d8 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraResolutionList.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraResolutionList.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.io.Serializable; import java.util.ArrayList; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraResource.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraResource.java similarity index 92% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraResource.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraResource.java index 3361877..7bf1e91 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraResource.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraResource.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.io.Serializable; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraSearchResult.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraSearchResult.java similarity index 96% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraSearchResult.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraSearchResult.java index 8eb7277..900d1f9 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraSearchResult.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraSearchResult.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.io.Serializable; import java.util.List; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraServerInfo.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraServerInfo.java similarity index 95% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraServerInfo.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraServerInfo.java index 3e63647..14f4d52 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraServerInfo.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraServerInfo.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; public class JiraServerInfo extends JiraResource { diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraSession.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraSession.java similarity index 93% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraSession.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraSession.java index 2e11c79..a368178 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraSession.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraSession.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.io.Serializable; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraTransition.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraTransition.java similarity index 94% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraTransition.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraTransition.java index 32da31a..85c5498 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraTransition.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraTransition.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraTransitions.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraTransitions.java similarity index 94% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraTransitions.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraTransitions.java index 23c970f..56ed8fe 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraTransitions.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraTransitions.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.io.Serializable; import java.util.List; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraUser.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraUser.java similarity index 94% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraUser.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraUser.java index 96154d5..2e408a6 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraUser.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraUser.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; public class JiraUser extends JiraNamedResource { diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraVersion.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraVersion.java similarity index 86% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraVersion.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraVersion.java index 4133ad0..a3d9f7f 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraVersion.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraVersion.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; public class JiraVersion extends JiraNamedResource { diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraVersionsList.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraVersionsList.java similarity index 81% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraVersionsList.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraVersionsList.java index 075c654..fff280b 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/JiraVersionsList.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/JiraVersionsList.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import java.util.ArrayList; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/WellKnownCustomFieldType.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/WellKnownCustomFieldType.java similarity index 96% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/WellKnownCustomFieldType.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/WellKnownCustomFieldType.java index 63c2718..c0c3fb6 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/WellKnownCustomFieldType.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/WellKnownCustomFieldType.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; public enum WellKnownCustomFieldType { LABELS("com.atlassian.jira.plugin.system.customfieldtypes:labels"), diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/WellKnownJiraField.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/WellKnownJiraField.java similarity index 96% rename from fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/WellKnownJiraField.java rename to fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/WellKnownJiraField.java index c45e7e1..e0e1d97 100644 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/domain/WellKnownJiraField.java +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/domain/WellKnownJiraField.java @@ -1,4 +1,4 @@ -package io.fluentqa.jira.domain; +package io.fluent.jira.domain; import de.cronn.reflection.util.PropertyGetter; import de.cronn.reflection.util.PropertyUtils; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/package-info.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/package-info.java new file mode 100644 index 0000000..c642f78 --- /dev/null +++ b/fluent-wrappers/fluent-jira/src/main/java/io/fluent/jira/package-info.java @@ -0,0 +1 @@ +package io.fluent.jira; diff --git a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/package-info.java b/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/package-info.java deleted file mode 100644 index 4c96b8f..0000000 --- a/fluent-wrappers/fluent-jira/src/main/java/io/fluentqa/jira/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package io.fluentqa.jira; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/MindMapAccessor.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/MindMapAccessor.java similarity index 87% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/MindMapAccessor.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/MindMapAccessor.java index aefed58..81ec664 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/MindMapAccessor.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/MindMapAccessor.java @@ -1,7 +1,8 @@ -package io.fluentqa.mindmap.api; +package io.fluent.mindmap.api; + +import io.fluent.mindmap.freemind.FreeMindTransformer; +import io.fluent.mindmap.xmind.XmindTransformer; -import io.fluentqa.mindmap.freemind.FreeMindTransformer; -import io.fluentqa.mindmap.xmind.XmindTransformer; import java.util.List; public class MindMapAccessor { diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/MindMapConvertConfig.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/MindMapConvertConfig.java similarity index 92% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/MindMapConvertConfig.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/MindMapConvertConfig.java index 05e5b64..7cf09ab 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/MindMapConvertConfig.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/MindMapConvertConfig.java @@ -1,4 +1,4 @@ -package io.fluentqa.mindmap.api; +package io.fluent.mindmap.api; import java.util.ArrayList; import java.util.List; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/MindMapPath.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/MindMapPath.java similarity index 94% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/MindMapPath.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/MindMapPath.java index 861f6dc..b3cd0bb 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/MindMapPath.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/MindMapPath.java @@ -1,4 +1,4 @@ -package io.fluentqa.mindmap.api; +package io.fluent.mindmap.api; import java.util.LinkedList; import lombok.Data; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/MindMapPathRecord.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/MindMapPathRecord.java similarity index 98% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/MindMapPathRecord.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/MindMapPathRecord.java index c0e7d12..727a88c 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/MindMapPathRecord.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/MindMapPathRecord.java @@ -1,4 +1,4 @@ -package io.fluentqa.mindmap.api; +package io.fluent.mindmap.api; import cn.hutool.core.bean.BeanUtil; import io.fluent.builtin.meta.ReflectionUtils; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/MindMapTransformer.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/MindMapTransformer.java similarity index 90% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/MindMapTransformer.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/MindMapTransformer.java index 16477f6..13fa297 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/MindMapTransformer.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/MindMapTransformer.java @@ -1,4 +1,4 @@ -package io.fluentqa.mindmap.api; +package io.fluent.mindmap.api; import java.util.List; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/MindmapTypeEnum.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/MindmapTypeEnum.java similarity index 94% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/MindmapTypeEnum.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/MindmapTypeEnum.java index 0e8dc1b..11818f1 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/MindmapTypeEnum.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/MindmapTypeEnum.java @@ -1,4 +1,4 @@ -package io.fluentqa.mindmap.api; +package io.fluent.mindmap.api; import io.fluent.builtin.JavaProjectFileUtils; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/NodeLevel.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/NodeLevel.java similarity index 84% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/NodeLevel.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/NodeLevel.java index 267af71..e8bf9ce 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/api/NodeLevel.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/api/NodeLevel.java @@ -1,4 +1,4 @@ -package io.fluentqa.mindmap.api; +package io.fluent.mindmap.api; import java.lang.annotation.*; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/exception/MindMapException.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/exception/MindMapException.java similarity index 92% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/exception/MindMapException.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/exception/MindMapException.java index 6ddf5ff..4b026e3 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/exception/MindMapException.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/exception/MindMapException.java @@ -1,4 +1,4 @@ -package io.fluentqa.mindmap.exception; +package io.fluent.mindmap.exception; public class MindMapException extends RuntimeException { public MindMapException() {} diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/FreeMindNode.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/FreeMindNode.java similarity index 76% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/FreeMindNode.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/FreeMindNode.java index a2cb3e2..31c0a57 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/FreeMindNode.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/FreeMindNode.java @@ -1,7 +1,7 @@ -package io.fluentqa.mindmap.freemind; +package io.fluent.mindmap.freemind; -import io.fluentqa.mindmap.api.MindMapPath; -import io.fluentqa.mindmap.freemind.model.Node; +import io.fluent.mindmap.api.MindMapPath; +import io.fluent.mindmap.freemind.model.Node; public class FreeMindNode extends MindMapPath { diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/FreeMindTransformer.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/FreeMindTransformer.java similarity index 88% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/FreeMindTransformer.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/FreeMindTransformer.java index c994778..0f6746c 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/FreeMindTransformer.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/FreeMindTransformer.java @@ -1,12 +1,12 @@ -package io.fluentqa.mindmap.freemind; +package io.fluent.mindmap.freemind; import io.fluent.builtin.XmlUtils; -import io.fluentqa.mindmap.api.MindMapConvertConfig; -import io.fluentqa.mindmap.api.MindMapPath; -import io.fluentqa.mindmap.api.MindMapPathRecord; -import io.fluentqa.mindmap.api.MindMapTransformer; -import io.fluentqa.mindmap.freemind.model.Map; -import io.fluentqa.mindmap.freemind.model.Node; +import io.fluent.mindmap.api.MindMapConvertConfig; +import io.fluent.mindmap.api.MindMapPath; +import io.fluent.mindmap.api.MindMapPathRecord; +import io.fluent.mindmap.api.MindMapTransformer; +import io.fluent.mindmap.freemind.model.Map; +import io.fluent.mindmap.freemind.model.Node; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Arrowlink.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Arrowlink.java similarity index 99% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Arrowlink.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Arrowlink.java index 4e29899..472c39e 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Arrowlink.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Arrowlink.java @@ -5,7 +5,7 @@ // 生成时间: 2022.09.23 时间 08:46:06 PM CST // -package io.fluentqa.mindmap.freemind.model; +package io.fluent.mindmap.freemind.model; import jakarta.xml.bind.annotation.*; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Attribute.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Attribute.java similarity index 97% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Attribute.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Attribute.java index beabd13..4d8c3e3 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Attribute.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Attribute.java @@ -5,7 +5,7 @@ // 生成时间: 2022.09.23 时间 08:46:06 PM CST // -package io.fluentqa.mindmap.freemind.model; +package io.fluent.mindmap.freemind.model; import jakarta.xml.bind.annotation.*; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/AttributeLayout.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/AttributeLayout.java similarity index 97% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/AttributeLayout.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/AttributeLayout.java index 4b8836e..8f96380 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/AttributeLayout.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/AttributeLayout.java @@ -5,7 +5,7 @@ // 生成时间: 2022.09.23 时间 08:46:06 PM CST // -package io.fluentqa.mindmap.freemind.model; +package io.fluent.mindmap.freemind.model; import jakarta.xml.bind.annotation.*; import java.math.BigInteger; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Cloud.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Cloud.java similarity index 96% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Cloud.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Cloud.java index f2cfc2a..0dc2343 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Cloud.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Cloud.java @@ -5,7 +5,7 @@ // 生成时间: 2022.09.23 时间 08:46:06 PM CST // -package io.fluentqa.mindmap.freemind.model; +package io.fluent.mindmap.freemind.model; import jakarta.xml.bind.annotation.*; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Edge.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Edge.java similarity index 98% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Edge.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Edge.java index 6719d30..10db299 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Edge.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Edge.java @@ -5,7 +5,7 @@ // 生成时间: 2022.09.23 时间 08:46:06 PM CST // -package io.fluentqa.mindmap.freemind.model; +package io.fluent.mindmap.freemind.model; import jakarta.xml.bind.annotation.*; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Font.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Font.java similarity index 98% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Font.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Font.java index 34bc2c1..b4dba65 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Font.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Font.java @@ -5,7 +5,7 @@ // 生成时间: 2022.09.23 时间 08:46:06 PM CST // -package io.fluentqa.mindmap.freemind.model; +package io.fluent.mindmap.freemind.model; import jakarta.xml.bind.annotation.*; import java.math.BigInteger; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Hook.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Hook.java similarity index 98% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Hook.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Hook.java index f6930c0..7f33895 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Hook.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Hook.java @@ -5,7 +5,7 @@ // 生成时间: 2022.09.23 时间 08:46:06 PM CST // -package io.fluentqa.mindmap.freemind.model; +package io.fluent.mindmap.freemind.model; import jakarta.xml.bind.annotation.*; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Html.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Html.java similarity index 97% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Html.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Html.java index 5b9a44f..f7fec81 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Html.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Html.java @@ -5,7 +5,7 @@ // 生成时间: 2022.09.23 时间 08:46:06 PM CST // -package io.fluentqa.mindmap.freemind.model; +package io.fluent.mindmap.freemind.model; import jakarta.xml.bind.annotation.*; import java.util.ArrayList; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Icon.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Icon.java similarity index 96% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Icon.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Icon.java index f50b327..6751303 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Icon.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Icon.java @@ -5,7 +5,7 @@ // 生成时间: 2022.09.23 时间 08:46:06 PM CST // -package io.fluentqa.mindmap.freemind.model; +package io.fluent.mindmap.freemind.model; import jakarta.xml.bind.annotation.*; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Linktarget.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Linktarget.java similarity index 99% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Linktarget.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Linktarget.java index 17b25c0..d9b48c0 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Linktarget.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Linktarget.java @@ -5,7 +5,7 @@ // 生成时间: 2022.09.23 时间 08:46:06 PM CST // -package io.fluentqa.mindmap.freemind.model; +package io.fluent.mindmap.freemind.model; import jakarta.xml.bind.annotation.*; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Map.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Map.java similarity index 97% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Map.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Map.java index 62af792..5448d3b 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Map.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Map.java @@ -5,7 +5,7 @@ // 生成时间: 2022.09.23 时间 08:46:06 PM CST // -package io.fluentqa.mindmap.freemind.model; +package io.fluent.mindmap.freemind.model; import jakarta.xml.bind.annotation.*; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Node.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Node.java similarity index 99% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Node.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Node.java index 4f97a80..c119228 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Node.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Node.java @@ -5,7 +5,7 @@ // 生成时间: 2022.09.23 时间 08:46:06 PM CST // -package io.fluentqa.mindmap.freemind.model; +package io.fluent.mindmap.freemind.model; import jakarta.xml.bind.annotation.*; import jakarta.xml.bind.annotation.adapters.CollapsedStringAdapter; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/ObjectFactory.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/ObjectFactory.java similarity index 98% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/ObjectFactory.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/ObjectFactory.java index efc3dd1..9450b5f 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/ObjectFactory.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/ObjectFactory.java @@ -5,7 +5,7 @@ // 生成时间: 2022.09.23 时间 08:46:06 PM CST // -package io.fluentqa.mindmap.freemind.model; +package io.fluent.mindmap.freemind.model; import jakarta.xml.bind.annotation.XmlRegistry; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Parameters.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Parameters.java similarity index 99% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Parameters.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Parameters.java index a639fbb..960c7fe 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Parameters.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Parameters.java @@ -5,7 +5,7 @@ // 生成时间: 2022.09.23 时间 08:46:06 PM CST // -package io.fluentqa.mindmap.freemind.model; +package io.fluent.mindmap.freemind.model; import jakarta.xml.bind.annotation.*; import java.math.BigInteger; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Richcontent.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Richcontent.java similarity index 97% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Richcontent.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Richcontent.java index 0e91af4..bd2dec3 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Richcontent.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Richcontent.java @@ -5,7 +5,7 @@ // 生成时间: 2022.09.23 时间 08:46:06 PM CST // -package io.fluentqa.mindmap.freemind.model; +package io.fluent.mindmap.freemind.model; import jakarta.xml.bind.annotation.*; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Text.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Text.java similarity index 95% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Text.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Text.java index d6e535f..7f0e79a 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/freemind/model/Text.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/freemind/model/Text.java @@ -5,7 +5,7 @@ // 生成时间: 2022.09.23 时间 08:46:06 PM CST // -package io.fluentqa.mindmap.freemind.model; +package io.fluent.mindmap.freemind.model; import jakarta.xml.bind.annotation.XmlAccessType; import jakarta.xml.bind.annotation.XmlAccessorType; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/package-info.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/package-info.java new file mode 100644 index 0000000..c0f43e5 --- /dev/null +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/package-info.java @@ -0,0 +1 @@ +package io.fluent.mindmap; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/XMindNode.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/XMindNode.java similarity index 51% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/XMindNode.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/XMindNode.java index 45b8b42..e811f79 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/XMindNode.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/XMindNode.java @@ -1,7 +1,7 @@ -package io.fluentqa.mindmap.xmind; +package io.fluent.mindmap.xmind; -import io.fluentqa.mindmap.api.MindMapPath; -import io.fluentqa.mindmap.xmind.model.Attached; +import io.fluent.mindmap.xmind.model.Attached; +import io.fluent.mindmap.api.MindMapPath; public class XMindNode extends MindMapPath implements Cloneable { public XMindNode(Attached root) { diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/XMindUtil.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/XMindUtil.java similarity index 94% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/XMindUtil.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/XMindUtil.java index b78516a..145156d 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/XMindUtil.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/XMindUtil.java @@ -1,11 +1,12 @@ -package io.fluentqa.mindmap.xmind; +package io.fluent.mindmap.xmind; import cn.hutool.core.compress.ZipReader; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.ZipUtil; -import io.fluentqa.mindmap.exception.MindMapException; -import io.fluentqa.mindmap.xmind.model.XmindRawData; +import io.fluent.mindmap.xmind.model.XmindRawData; +import io.fluent.mindmap.exception.MindMapException; + import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/XmindTransformer.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/XmindTransformer.java similarity index 88% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/XmindTransformer.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/XmindTransformer.java index f5ef381..5555b88 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/XmindTransformer.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/XmindTransformer.java @@ -1,13 +1,14 @@ -package io.fluentqa.mindmap.xmind; +package io.fluent.mindmap.xmind; import cn.hutool.json.JSONUtil; -import io.fluentqa.mindmap.api.MindMapConvertConfig; -import io.fluentqa.mindmap.api.MindMapPath; -import io.fluentqa.mindmap.api.MindMapPathRecord; -import io.fluentqa.mindmap.api.MindMapTransformer; -import io.fluentqa.mindmap.xmind.model.Attached; -import io.fluentqa.mindmap.xmind.model.JsonRootBean; -import io.fluentqa.mindmap.xmind.model.XmindRawData; +import io.fluent.mindmap.xmind.model.Attached; +import io.fluent.mindmap.xmind.model.JsonRootBean; +import io.fluent.mindmap.xmind.model.XmindRawData; +import io.fluent.mindmap.api.MindMapConvertConfig; +import io.fluent.mindmap.api.MindMapPath; +import io.fluent.mindmap.api.MindMapPathRecord; +import io.fluent.mindmap.api.MindMapTransformer; + import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/Attached.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/Attached.java similarity index 83% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/Attached.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/Attached.java index d39006d..fdb5244 100755 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/Attached.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/Attached.java @@ -1,4 +1,4 @@ -package io.fluentqa.mindmap.xmind.model; +package io.fluent.mindmap.xmind.model; import java.util.List; import lombok.Data; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/Children.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/Children.java similarity index 73% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/Children.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/Children.java index 96a5cb5..780973a 100755 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/Children.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/Children.java @@ -1,4 +1,4 @@ -package io.fluentqa.mindmap.xmind.model; +package io.fluent.mindmap.xmind.model; import java.util.List; import lombok.Data; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/Comments.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/Comments.java similarity index 76% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/Comments.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/Comments.java index 72b7b70..875a00b 100755 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/Comments.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/Comments.java @@ -1,4 +1,4 @@ -package io.fluentqa.mindmap.xmind.model; +package io.fluent.mindmap.xmind.model; import lombok.Data; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/JsonRootBean.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/JsonRootBean.java similarity index 76% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/JsonRootBean.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/JsonRootBean.java index 20e984d..08ac87a 100755 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/JsonRootBean.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/JsonRootBean.java @@ -1,4 +1,4 @@ -package io.fluentqa.mindmap.xmind.model; +package io.fluent.mindmap.xmind.model; import lombok.Data; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/Notes.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/Notes.java similarity index 65% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/Notes.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/Notes.java index c563e3d..ab40ce6 100755 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/Notes.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/Notes.java @@ -1,4 +1,4 @@ -package io.fluentqa.mindmap.xmind.model; +package io.fluent.mindmap.xmind.model; import lombok.Data; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/RootTopic.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/RootTopic.java similarity index 83% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/RootTopic.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/RootTopic.java index 53dcbe9..5333dc5 100755 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/RootTopic.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/RootTopic.java @@ -1,4 +1,4 @@ -package io.fluentqa.mindmap.xmind.model; +package io.fluent.mindmap.xmind.model; import java.util.List; import lombok.Data; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/XmindRawData.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/XmindRawData.java similarity index 96% rename from fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/XmindRawData.java rename to fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/XmindRawData.java index 2761267..7009dc5 100644 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/xmind/model/XmindRawData.java +++ b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluent/mindmap/xmind/model/XmindRawData.java @@ -1,4 +1,4 @@ -package io.fluentqa.mindmap.xmind.model; +package io.fluent.mindmap.xmind.model; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONArray; diff --git a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/package-info.java b/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/package-info.java deleted file mode 100644 index 3ce5b18..0000000 --- a/fluent-wrappers/fluent-mindmap/src/main/java/io/fluentqa/mindmap/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package io.fluentqa.mindmap; diff --git a/fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/api/DemoBean.java b/fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/api/DemoBean.java similarity index 89% rename from fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/api/DemoBean.java rename to fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/api/DemoBean.java index 36d160b..03390f0 100644 --- a/fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/api/DemoBean.java +++ b/fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/api/DemoBean.java @@ -1,4 +1,4 @@ -package io.fluentqa.mindmap.api; +package io.fluent.mindmap.api; import lombok.Data; diff --git a/fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/api/DemoBeanConfig.java b/fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/api/DemoBeanConfig.java similarity index 94% rename from fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/api/DemoBeanConfig.java rename to fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/api/DemoBeanConfig.java index 0e33039..c35e198 100644 --- a/fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/api/DemoBeanConfig.java +++ b/fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/api/DemoBeanConfig.java @@ -1,4 +1,4 @@ -package io.fluentqa.mindmap.api; +package io.fluent.mindmap.api; public class DemoBeanConfig { diff --git a/fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/api/DemoBeanWOLevel.java b/fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/api/DemoBeanWOLevel.java similarity index 86% rename from fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/api/DemoBeanWOLevel.java rename to fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/api/DemoBeanWOLevel.java index 77b9a7d..a889473 100644 --- a/fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/api/DemoBeanWOLevel.java +++ b/fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/api/DemoBeanWOLevel.java @@ -1,4 +1,4 @@ -package io.fluentqa.mindmap.api; +package io.fluent.mindmap.api; import lombok.Data; diff --git a/fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/api/MindMapAccessorTest.java b/fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/api/MindMapAccessorTest.java similarity index 95% rename from fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/api/MindMapAccessorTest.java rename to fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/api/MindMapAccessorTest.java index 2cadd5b..a6b8d71 100644 --- a/fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/api/MindMapAccessorTest.java +++ b/fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/api/MindMapAccessorTest.java @@ -1,4 +1,4 @@ -package io.fluentqa.mindmap.api; +package io.fluent.mindmap.api; import java.util.List; import org.junit.jupiter.api.Test; diff --git a/fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/freemind/FreeMindConverterTest.java b/fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/freemind/FreeMindConverterTest.java similarity index 74% rename from fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/freemind/FreeMindConverterTest.java rename to fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/freemind/FreeMindConverterTest.java index 9f5727e..b61be43 100644 --- a/fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/freemind/FreeMindConverterTest.java +++ b/fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/freemind/FreeMindConverterTest.java @@ -1,7 +1,8 @@ -package io.fluentqa.mindmap.freemind; +package io.fluent.mindmap.freemind; + +import io.fluent.mindmap.api.MindMapPath; +import io.fluent.mindmap.freemind.model.Node; -import io.fluentqa.mindmap.api.MindMapPath; -import io.fluentqa.mindmap.freemind.model.Node; import java.util.List; import org.junit.jupiter.api.BeforeEach; diff --git a/fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/xmind/XMindUtilTest.java b/fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/xmind/XMindUtilTest.java similarity index 84% rename from fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/xmind/XMindUtilTest.java rename to fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/xmind/XMindUtilTest.java index cc7bec9..22ae77d 100644 --- a/fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/xmind/XMindUtilTest.java +++ b/fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/xmind/XMindUtilTest.java @@ -1,6 +1,6 @@ -package io.fluentqa.mindmap.xmind; +package io.fluent.mindmap.xmind; -import io.fluentqa.mindmap.xmind.model.XmindRawData; +import io.fluent.mindmap.xmind.model.XmindRawData; import org.junit.jupiter.api.Test; class XMindUtilTest { diff --git a/fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/xmind/XmindTransformerTest.java b/fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/xmind/XmindTransformerTest.java similarity index 74% rename from fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/xmind/XmindTransformerTest.java rename to fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/xmind/XmindTransformerTest.java index f307acc..f655e60 100644 --- a/fluent-wrappers/fluent-mindmap/src/test/java/io/fluentqa/mindmap/xmind/XmindTransformerTest.java +++ b/fluent-wrappers/fluent-mindmap/src/test/java/io/fluent/mindmap/xmind/XmindTransformerTest.java @@ -1,7 +1,8 @@ -package io.fluentqa.mindmap.xmind; +package io.fluent.mindmap.xmind; + +import io.fluent.mindmap.api.MindMapPath; +import io.fluent.mindmap.xmind.model.Attached; -import io.fluentqa.mindmap.api.MindMapPath; -import io.fluentqa.mindmap.xmind.model.Attached; import java.util.List; import org.junit.jupiter.api.Test; diff --git a/fluent-wrappers/fluent-quickdao/sample.db b/fluent-wrappers/fluent-quickdao/sample.db new file mode 100644 index 0000000..e69de29 diff --git a/fluent-wrappers/fluent-quickdao/src/main/java/io/fluent/quickdao/QuickDao.java b/fluent-wrappers/fluent-quickdao/src/main/java/io/fluent/quickdao/QuickDao.java index c9dd265..41eb4fa 100644 --- a/fluent-wrappers/fluent-quickdao/src/main/java/io/fluent/quickdao/QuickDao.java +++ b/fluent-wrappers/fluent-quickdao/src/main/java/io/fluent/quickdao/QuickDao.java @@ -22,6 +22,7 @@ public class QuickDao { Db db; DataSource ds; + public static QuickDao createDao(T dsConfig) { QuickDao dao = new QuickDao(); dao.dsConfig = dsConfig; diff --git a/fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/MarkdownAccessor.java b/fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/MarkdownAccessor.java similarity index 58% rename from fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/MarkdownAccessor.java rename to fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/MarkdownAccessor.java index 71c6e55..b452338 100644 --- a/fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/MarkdownAccessor.java +++ b/fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/MarkdownAccessor.java @@ -1,3 +1,3 @@ -package io.fluentqa.md; +package io.fluent.md; public class MarkdownAccessor {} diff --git a/fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/package-info.java b/fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/package-info.java new file mode 100644 index 0000000..93f2e6c --- /dev/null +++ b/fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/package-info.java @@ -0,0 +1 @@ +package io.fluent.md; diff --git a/fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/parser/FieldParseConfig.java b/fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/parser/FieldParseConfig.java similarity index 86% rename from fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/parser/FieldParseConfig.java rename to fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/parser/FieldParseConfig.java index d4a5c1c..90949b9 100644 --- a/fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/parser/FieldParseConfig.java +++ b/fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/parser/FieldParseConfig.java @@ -1,4 +1,4 @@ -package io.fluentqa.md.parser; +package io.fluent.md.parser; import java.util.function.Function; diff --git a/fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/parser/ParseConfig.java b/fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/parser/ParseConfig.java similarity index 93% rename from fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/parser/ParseConfig.java rename to fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/parser/ParseConfig.java index aff5edb..4c329f5 100644 --- a/fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/parser/ParseConfig.java +++ b/fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/parser/ParseConfig.java @@ -1,4 +1,4 @@ -package io.fluentqa.md.parser; +package io.fluent.md.parser; import cn.hutool.core.util.ReflectUtil; import java.util.ArrayList; diff --git a/fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/parser/awesome/AwesomeListParserConfig.java b/fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/parser/awesome/AwesomeListParserConfig.java similarity index 76% rename from fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/parser/awesome/AwesomeListParserConfig.java rename to fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/parser/awesome/AwesomeListParserConfig.java index 856eaeb..47c8705 100644 --- a/fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/parser/awesome/AwesomeListParserConfig.java +++ b/fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/parser/awesome/AwesomeListParserConfig.java @@ -1,6 +1,6 @@ -package io.fluentqa.md.parser.awesome; +package io.fluent.md.parser.awesome; -import io.fluentqa.md.parser.FieldParseConfig; +import io.fluent.md.parser.FieldParseConfig; import lombok.Data; @Data diff --git a/fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/parser/awesome/AwesomeModel.java b/fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/parser/awesome/AwesomeModel.java similarity index 79% rename from fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/parser/awesome/AwesomeModel.java rename to fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/parser/awesome/AwesomeModel.java index e9f23c6..12dba73 100644 --- a/fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/parser/awesome/AwesomeModel.java +++ b/fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/parser/awesome/AwesomeModel.java @@ -1,4 +1,4 @@ -package io.fluentqa.md.parser.awesome; +package io.fluent.md.parser.awesome; import lombok.Data; diff --git a/fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/parser/awesome/MarkdownAwesomeListParser.java b/fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/parser/awesome/MarkdownAwesomeListParser.java similarity index 97% rename from fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/parser/awesome/MarkdownAwesomeListParser.java rename to fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/parser/awesome/MarkdownAwesomeListParser.java index c45bbe3..17539c8 100644 --- a/fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/parser/awesome/MarkdownAwesomeListParser.java +++ b/fluent-wrappers/fluentqa-md/src/main/java/io/fluent/md/parser/awesome/MarkdownAwesomeListParser.java @@ -1,4 +1,4 @@ -package io.fluentqa.md.parser.awesome; +package io.fluent.md.parser.awesome; import com.vladsch.flexmark.html.HtmlRenderer; import com.vladsch.flexmark.parser.Parser; diff --git a/fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/package-info.java b/fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/package-info.java deleted file mode 100644 index cd7930c..0000000 --- a/fluent-wrappers/fluentqa-md/src/main/java/io/fluentqa/md/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package io.fluentqa.md; diff --git a/fluent-wrappers/fluentqa-md/src/test/java/io/fluentqa/md/parsers/MarkdownAwesomeListParserTest.java b/fluent-wrappers/fluentqa-md/src/test/java/io/fluent/md/parsers/MarkdownAwesomeListParserTest.java similarity index 95% rename from fluent-wrappers/fluentqa-md/src/test/java/io/fluentqa/md/parsers/MarkdownAwesomeListParserTest.java rename to fluent-wrappers/fluentqa-md/src/test/java/io/fluent/md/parsers/MarkdownAwesomeListParserTest.java index 61fbe09..7b40749 100644 --- a/fluent-wrappers/fluentqa-md/src/test/java/io/fluentqa/md/parsers/MarkdownAwesomeListParserTest.java +++ b/fluent-wrappers/fluentqa-md/src/test/java/io/fluent/md/parsers/MarkdownAwesomeListParserTest.java @@ -1,4 +1,4 @@ -package io.fluentqa.md.parsers; +package io.fluent.md.parsers; import cn.hutool.json.JSONUtil; import com.vladsch.flexmark.ast.BulletList; @@ -8,8 +8,9 @@ import com.vladsch.flexmark.parser.Parser; import com.vladsch.flexmark.util.ast.Node; import io.fluent.builtin.JavaProjectFileUtils; -import io.fluentqa.md.parser.awesome.AwesomeModel; -import io.fluentqa.md.parser.awesome.MarkdownAwesomeListParser; +import io.fluent.md.parser.awesome.AwesomeModel; +import io.fluent.md.parser.awesome.MarkdownAwesomeListParser; + import java.io.File; import java.nio.charset.Charset; import java.util.List; diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/Mock.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/Mock.java deleted file mode 100644 index 5c988ba..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/Mock.java +++ /dev/null @@ -1,492 +0,0 @@ -package io.fluent.mocker; - - -import com.forte.util.exception.MockException; -import com.forte.util.factory.MockMapperFactory; -import com.forte.util.factory.MockObjectFactory; -import com.forte.util.factory.MockProxyHandlerFactory; -import com.forte.util.factory.MockProxyHandlerFactoryImpl; -import com.forte.util.loader.DefaultMockMethodLoader; -import com.forte.util.loader.MethodLoader; -import com.forte.util.mockbean.*; -import com.forte.util.parser.ParameterParser; -import com.forte.util.utils.ClassScanner; -import com.forte.util.utils.MockUtil; -import com.forte.util.utils.ProxyUtils; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -/** - *

- * javaBean假数据生成工具 - *

- *

- * 使用静态方法:{@link #set(Class, Map)} 来添加一个类的假数据类型映射
- * 语法基本与Mock.js中的类似,字符串参数中可以使用@+方法名的方式指定随机方法(随机方法详见{@link MockUtil},此类也可以直接使用) - *

- *

- *

    - *
  • 使用的时候,请务必保证填充假数据的字段有他的getter方法
  • - *
  • 使用多层级赋值的时候,请注意保证多层级中涉及的深层对象有无参构造方法
  • - *
- *

- *

- * 为类中的引用类型对象赋值的时候,有两种方式: - *

    - *
  • - * - * map.set("user" , new HashMap) - * - * -> 即为字段再配置一个map映射集合 - *
  • - *
  • - * - * map.set("user.name" , "@cname") - * - * -> 使用"."分割,即使用多层级对象赋值,此方式需要保证引用类型的对象有无参构造,且字段有getter方法 - *
  • - *
- *

- * - * @author ForteScarlet - * @version 0.5-beta - */ -public class Mock { - - /* 静态代码块加载资源 */ - static { - //创建线程安全的map集合,保存全部映射记录 - MOCK_OBJECT = new ConcurrentHashMap<>(4); - MOCK_MAP = new ConcurrentHashMap<>(4); - - //创建map,这里的map理论上不需要线程同步 - Map mockUtilMethods; - - //加载这些方法,防止每次都使用反射去调用方法。 - //直接调用的话无法掌控参数,所以必须使用反射的形式进行调用 - Class mockUtilClass = MockUtil.class; - //只获取公共方法 - Method[] methods = mockUtilClass.getMethods(); - /* - 过滤Object中的方法、 - 将MockUtil中的全部方法名格式化 格式:方法名(参数类型class地址,参数类型class地址.....)、 - 转化为<方法名:方法>的map集合 - */ - mockUtilMethods = - Arrays.stream(methods) - //过滤掉Object中继承过来的方法 - .filter(m -> Arrays.stream(Object.class.getMethods()).noneMatch(om -> om.equals(m))) - //格式化方法名,格式:方法名(参数类型class地址,参数类型class地址.....) - .flatMap(m -> { - Map methodMap = new HashMap<>(); - //格式化方法名,并作为key - String key = m.getName() + "(" - + Arrays.stream(m.getParameterTypes()) - .map(Class::getName) - .collect(Collectors.joining(",")) + - ")"; - methodMap.put(key, m); - return methodMap.entrySet().stream(); - }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - - //保存MockUtil中的全部方法 - MOCK_METHOD = mockUtilMethods; - } - - /** - * 保存全部记录的class与其对应的假对象{@link MockBean} - */ - private static final Map MOCK_OBJECT; - - /** - * Map类型假对象 - * TODO 后期考虑合并MOCK_OBJECT 和 MOCK_MAP两个字段 - */ - private static final Map MOCK_MAP; - - - /** - * MockUtil中的全部方法 - */ - private static final Map MOCK_METHOD; - - - /** - * 添加一个数据映射 - * - * @param objClass 映射类型 - * @param map 映射对应值 - * @return 映射结果表 - */ - public static MockBean setResult(Class objClass, Map map, boolean reset) { - //如果不是重新设置且此映射已经存在,并且objClass对象存在,将会抛出异常 - if (!reset && MOCK_OBJECT.get(objClass) != null) { - throw new MockException("此映射已存在!"); - } - - MockBean parser; - - //使用参数解析器进行解析 - parser = ParameterParser.parser(objClass, map); - - //如果类型不是Map类型,添加 - MOCK_OBJECT.put(objClass, new MockNormalObject<>(parser)); - - //提醒系统的垃圾回收 - System.gc(); - - return parser; - } - - /** - * 添加一个map类型的映射 - * - * @param resultName 映射名 - * @param map 映射值 - * @param reset 是否覆盖 - */ - public static MockMapBean setResult(String resultName, Map map, boolean reset) { - //如果不是重新设置且此映射已经存在,并且objClass对象存在,将会抛出异常 - if (!reset && MOCK_MAP.get(resultName) != null) { - throw new MockException("此映射已存在!this mock result has already exists."); - } - - MockMapBean parser; - - //使用参数解析器进行解析 - parser = ParameterParser.parser(map); - MOCK_MAP.put(resultName, MockObjectFactory.createMapObj(parser)); - - //提醒系统的垃圾回收 - System.gc(); - - return parser; - } - - - /** - * 添加数据记录,如果要添加的映射已存在,则会抛出异常 - * - * @param objClass 映射的class - * @param map

映射的规则对象

- *

- *

    - *
  • key:对应的字段
  • - *
  • - * value:映射参数,可以是: - *
      - *
    • 字符串
    • - *
    • 若干随机方法指令(指令详见{@link MockUtil})
    • - *
    • 整数(Integer)
    • - *
    • 浮点数(Double)
    • - *
    • 数组或集合类型
    • - *
    • Map集合类型(可作为新的映射,也可直接作为参数)
    • - *
    • 任意引用数据类型
    • - *
    - *
  • - *
- *

- *

- * 如果映射的对象中有多层级对象,支持使用多层级字段映射,例如:
- * - * map.put("friend.name" , "@cname"); - * - *

- */ - public static void set(Class objClass, Map map) { - //设置并保存映射,不可覆盖 - setResult(objClass, map, false); - } - - /** - * {@link #set(Class, Map)} and {@link #get(Class)} - */ - public static MockObject setAndGet(Class objClass, Map map){ - set(objClass, map); - return get(objClass); - } - - /** - * 通过注解来获取映射 - */ - public static void set(Class objClass) { - //获取映射Map - Map mapper = MockMapperFactory.getMapper(objClass); - setResult(objClass, mapper, false); - } - - /** - * {@link #set(Class, Map)} and {@link #get(Class)} - */ - public static MockObject setAndGet(Class objClass){ - set(objClass); - return get(objClass); - } - - /** - * 通过注解来获取映射, 并提供额外的、难以用注解进行表达的映射参数 - */ - public static void setWithOther(Class objClass, Map other) { - //获取映射Map - Map mapper = MockMapperFactory.getMapper(objClass, other); - setResult(objClass, mapper, false); - } - - - /** - * 添加数据记录,如果要添加的映射已存在,则会抛出异常 - * - * @param resultName - * @param map - */ - public static void set(String resultName, Map map) { - //设置并保存映射,不可覆盖 - setResult(resultName, map, false); - } - - - /** - * {@link #set(Class, Map)} and {@link #get(Class)} - */ - public static MockObject setAndGet(String resultName, Map map){ - set(resultName, map); - return get(resultName); - } - - - /** - * 添加数据记录,如果要添加的映射已存在,则会覆盖 - * - * @param objClass - * @param map - * @param - */ - public static void reset(Class objClass, Map map) { - //设置并保存映射 - setResult(objClass, map, true); - } - - /** - * 通过注解来获取映射 - */ - public static void reset(Class objClass) { - //获取映射Map - Map mapper = MockMapperFactory.getMapper(objClass); - setResult(objClass, mapper, true); - } - - /** - * 通过注解来获取映射, 并提供额外的、难以用注解进行表达的映射参数 - */ - public static void resetWithOther(Class objClass, Map other) { - //获取映射Map - Map mapper = MockMapperFactory.getMapper(objClass, other); - setResult(objClass, mapper, true); - } - - - /** - * 添加数据记录,如果要添加的映射已存在,则会覆盖 - * - * @param resultName - * @param map - * @param - */ - public static void reset(String resultName, Map map) { - //设置并保存映射 - setResult(resultName, map, true); - } - - - /** - * 获取一个实例对象 - * - * @param objClass - * @param - * @return - */ - public static MockObject get(Class objClass) { - return Optional.ofNullable(MOCK_OBJECT.get(objClass)).orElse(null); - } - - /** - * 获取一个实例对象 - * - * @param resultName - * @param - * @return - */ - public static MockObject get(String resultName) { - return Optional.ofNullable(MOCK_MAP.get(resultName)).orElse(null); - } - - /** - * 扫描包路径,加载标记了{@link com.forte.util.mapper.MockBean}注解的类。 - * - * @param classLoader nullable, 类加载器, null则默认为当前类加载器 - * @param withOther nullable, 假如扫描的类中存在某些类,你想要为它提供一些额外的参数,此函数用于获取对应class所需要添加的额外参数。可以为null - * @param reset 加载注解映射的时候是否使用reset - * @param packages emptyable, 要扫描的包路径列表, 为空则直接返回空set - * @return 扫描并加载成功的类 - * @throws Exception 包扫描过程中可能会出现一些例如类找不到等各种异常。需要进行处理。 - */ - public static Set> scan(ClassLoader classLoader, Function, Map> withOther, boolean reset, String... packages) throws Exception { - if (packages.length == 0) { - return new HashSet<>(); - } - // 包扫描器 - final ClassScanner scanner = classLoader == null ? new ClassScanner() : new ClassScanner(classLoader); - - // 扫描所有的包路径 - for (String p : packages) { - scanner.find(p, c -> c.getAnnotation(com.forte.util.mapper.MockBean.class) != null); - } - - // 扫描完了之后,load - final Set> classes = scanner.get(); - - classes.forEach(c -> { - if (withOther != null) { - if (reset) { - resetWithOther(c, withOther.apply(c)); - } else { - setWithOther(c, withOther.apply(c)); - } - } else { - if (reset) { - reset(c); - } else { - set(c); - } - } - }); - - return classes; - } - - /** - * {@link #scan(ClassLoader, Function, boolean, String...)}的重载方法 - * - * @see #scan(ClassLoader, Function, boolean, String...) - */ - public static Set> scan(Function, Map> withOther, boolean reset, String... packages) throws Exception { - return scan(null, withOther, reset, packages); - } - - /** - * {@link #scan(ClassLoader, Function, boolean, String...)}的重载方法 - * - * @see #scan(ClassLoader, Function, boolean, String...) - */ - public static Set> scan(boolean reset, String... packages) throws Exception { - return scan(null, null, reset, packages); - } - - /** - * {@link #scan(ClassLoader, Function, boolean, String...)}的重载方法 - * reset默认为false - * - * @see #scan(ClassLoader, Function, boolean, String...) - */ - public static Set> scan(String... packages) throws Exception { - return scan(null, null, false, packages); - } - - /** - *
 为一个接口提供一个代理对象。此接口中,所有的 抽象方法 都会被扫描,假如他的返回值存在与Mock中,则为其创建代理。
-     * 
 此方法默认不会为使用者保存单例,每次代理都会代理一个新的对象,因此如果有需要,请保存一个单例对象而不是频繁代理。
-     * @param type    要代理的接口类型。
-     * @param factory 接口代理处理器的获取工厂。可自行实现。
-     * @param  接口类型
-     * @return 代理结果
-     */
-    public static  T proxy(Class type, MockProxyHandlerFactory factory) {
-        // 验证是否为接口类型
-        if (!Modifier.isInterface(type.getModifiers())) {
-            throw new IllegalArgumentException("type ["+ type +"] is not a interface type.");
-        }
-
-        // 获取代理处理器
-        final InvocationHandler proxyHandler = factory.getHandler((returnType, name) -> {
-            MockObject mockObject = null;
-            if (name != null) {
-                mockObject = get(name);
-            }
-            if (mockObject == null) {
-                mockObject = get(returnType);
-            }
-            return mockObject;
-        });
-
-        // 返回结果
-        return ProxyUtils.proxy(type, proxyHandler);
-    }
-
-    /**
-     * 
 为一个接口提供一个代理对象。此接口中,所有的 抽象方法 都会被扫描,假如他的返回值存在与Mock中,则为其创建代理。
-     * 
 此方法默认不会为使用者保存单例,每次代理都会代理一个新的对象,因此如果有需要,请保存一个单例对象而不是频繁代理。
-     * 
 使用默认的接口代理处理器工厂{@link MockProxyHandlerFactoryImpl}。
-     * 
 默认处理工厂中,代理接口时,被代理的方法需要:
-     * 
 不是default方法。default方法会根据其自己的逻辑执行。
-     * 
 没有参数
-     * 
 没有标注{@code @MockProxy(ignore=true) ignore=true的时候代表忽略}
-     * 
-     * @see MockProxyHandlerFactoryImpl
-     * @param type    要代理的接口类型。
-     * @return 接口代理
-     */
-    public static > T proxy(C type) {
-        return proxy(type, new MockProxyHandlerFactoryImpl());
-    }
-
-    /**
-     * 获取方法加载器
-     *
-     * @return
-     */
-    public static MethodLoader mockMethodLoader() {
-        return new DefaultMockMethodLoader(MOCK_METHOD);
-    }
-
-    /**
-     * Deprecated
-     *
-     * @see #getMockMethods()
-     */
-    @Deprecated
-    public static Map _getMockMethod() {
-        return getMockMethods();
-    }
-
-    /**
-     * 获取Mock方法集合
-     *
-     * @return 全部已被加载的映射方法
-     */
-    public static Map getMockMethods() {
-        return new HashMap<>(MOCK_METHOD);
-    }
-
-
-    /**
-     * 根据过滤条件寻找指定的string-method
-     */
-    public static Map.Entry getMockMethodByFilter(Predicate> predicate){
-        for (Map.Entry entry : MOCK_METHOD.entrySet()) {
-            if(predicate.test(entry)){
-                return entry;
-            }
-        }
-        return null;
-    }
-
-
-}
diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/MockConfiguration.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/MockConfiguration.java
deleted file mode 100644
index 2cbfc09..0000000
--- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/MockConfiguration.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package io.fluent.mocker;
-import javax.script.ScriptEngine;
-
-/**
- *
- * 这是一个静态类,你可以随时随地修改他的配置。
- * 他的一些配置会在某些地方用到。
- *
- * @author ForteScarlet  
- */
-public class MockConfiguration {
-
-    /**
-     * 

是否启用JS脚本执行。 - *

版本1.8之后将脚本执行类{@link ScriptEngine}变更为了复用的单例形式, - * 效率提升了约2倍多(测试生成1000条数据,优化前:14s左右,优化后:6s左右) - *

6秒还是太慢了,因此现在修改为默认情况下不开启JS脚本执行, - * 未开启配置的情况下,任何字符串类型的值都不再会尝试进行JS脚本执行。 - *

关闭脚本的效率比开启脚本的效率高15倍左右(测试生成1000条数据,开启JS:6左右,关闭JS:0.4秒左右) - *

- *

- * - */ - private static boolean enableJsScriptEngine = false; - - /** - * 配置是否开启JS脚本执行 - */ - public static synchronized void setEnableJsScriptEngine(boolean enableJsScriptEngine){ - MockConfiguration.enableJsScriptEngine = enableJsScriptEngine; - } - - /** - * 获取是否开启JS脚本执行。 - * @return - */ - public static boolean isEnableJsScriptEngine(){ - return enableJsScriptEngine; - } - - - - - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/exception/MockException.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/exception/MockException.java deleted file mode 100644 index fbc76d7..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/exception/MockException.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.fluent.mocker.exception; - - -public class MockException extends RuntimeException { - public MockException() { - } - public MockException(String message) { - super(message); - } - - public MockException(String message, Throwable cause) { - super(message, cause); - } - - public MockException(Throwable cause) { - super(cause); - } - - public MockException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/exception/MockParserException.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/exception/MockParserException.java deleted file mode 100644 index b4c98fa..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/exception/MockParserException.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.fluent.mocker.exception; - - -public class MockParserException extends MockException{ - - public MockParserException() { - } - public MockParserException(String message) { - super(message); - } - - public MockParserException(String message, Throwable cause) { - super(message, cause); - } - - public MockParserException(Throwable cause) { - super(cause); - } - - public MockParserException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/exception/ParameterSizeException.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/exception/ParameterSizeException.java deleted file mode 100644 index f448c24..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/exception/ParameterSizeException.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.fluent.mocker.exception; - -public class ParameterSizeException extends MockException { - public ParameterSizeException() { - super("参数数量与方法参数数量不符!"); - } -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/factory/MockBeanFactory.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/factory/MockBeanFactory.java deleted file mode 100644 index e8d6c91..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/factory/MockBeanFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.fluent.mocker.factory; - - -import io.fluent.mocker.mockbean.MockBean; -import io.fluent.mocker.mockbean.MockField; -import io.fluent.mocker.mockbean.MockMapBean; - - -public class MockBeanFactory { - - /** - * 创建一个MockBean - * @param objectClass - * @param fields - * @param - * @return - */ - public static MockBean createMockBean(Class objectClass, MockField[] fields){ - return new MockBean<>(objectClass, fields); - } - - /** - * 创建一个MockMapBean - * @param fields - * @return - */ - public static MockMapBean createMockMapBean(MockField[] fields){ - return new MockMapBean(fields); - } - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/factory/MockMapperFactory.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/factory/MockMapperFactory.java deleted file mode 100644 index b15d82d..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/factory/MockMapperFactory.java +++ /dev/null @@ -1,101 +0,0 @@ -package io.fluent.mocker.factory; - - -import org.apache.commons.beanutils.ConvertUtils; - -import java.util.AbstractMap; -import java.util.Arrays; -import java.util.Map; -import java.util.Objects; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -/** - * 生成映射Map的工厂 - * - * @author ForteScarlet <[email]ForteScarlet@163.com> - * @since JDK1.8 - **/ -public class MockMapperFactory { - - /** - * 通过一个类的注解来生成映射,然后再整合额外的指定参数 - * - * @param type 类型 - * @param other 额外参数,可以为null - */ - public static Map getMapper(Class type, Map other) { - Map mapper = Arrays.stream(type.getDeclaredFields()).map(f -> { - //由于目前只有两种注解,直接判断下就行了 - //优先使用MockValue的值 - Map.Entry, String> valueAndParam = getValue(f.getAnnotation(MockValue.class)); - if (valueAndParam == null) { - valueAndParam = getValue(f.getAnnotation(MockArray.class)); - } - // 无注解,返回null并由后续过滤 - if(valueAndParam == null){ - return null; - } - return new AbstractMap.SimpleEntry<>(f.getName() + valueAndParam.getValue(), valueAndParam.getKey().get()); - }).filter(Objects::nonNull).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - if(other != null){ - mapper.putAll(other); - } - return mapper; - } - - /** - * 通过一个类的注解来生成映射 - * - * @param type 类型 - */ - public static Map getMapper(Class type) { - return getMapper(type, null); - } - - /** - * 通过注解MockValue类型来获取value值 - * 如果为null或者值没有(保留空字符),则返回null - * @return {@code Entry, fieldParam>} , 返回一个entry,key为value中的值的获取函数,value为map映射中字段的区间参数值。 - */ - public static Map.Entry, String> getValue(MockValue mockValueAnnotation) { - if (mockValueAnnotation == null || mockValueAnnotation.value().length() <= 0) { - return null; - } - final String mapValue = mockValueAnnotation.value(); - final Class valueType = mockValueAnnotation.valueType(); - - Supplier valueGetter = valueType.equals(String.class) ? () -> mapValue : () -> ConvertUtils.convert(mapValue, valueType); - - String param = mockValueAnnotation.param().trim(); - if(param.length() > 0 && !param.startsWith("|")){ - param = "|" + param; - } - return new AbstractMap.SimpleEntry<>(valueGetter, param); - } - - /** - * 通过注解MockValue类型来获取value值 - * @return {@code Entry, fieldParam>} , 返回一个entry,key为value中的值的获取函数,value为map映射中字段的区间参数值。 - */ - public static Map.Entry, String> getValue(MockArray mockArrayAnnotation) { - if (mockArrayAnnotation == null) { - return null; - } - try { - ArrayMapper arrayMapper = mockArrayAnnotation.mapper().newInstance(); - final String[] mockArrayValue = mockArrayAnnotation.value(); - final Supplier valueGetter = () -> arrayMapper.map(mockArrayValue); - String param = mockArrayAnnotation.param().trim(); - if(param.length() > 0 && !param.startsWith("|")){ - param = "|" + param; - } - return new AbstractMap.SimpleEntry<>(valueGetter, param); - } catch (InstantiationException | IllegalAccessException e) { - throw new MockException("无法实例化数组转化器 Cannot instantiate an array converter :" + mockArrayAnnotation.mapper()); - } - } - - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/factory/MockObjectFactory.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/factory/MockObjectFactory.java deleted file mode 100644 index cf4700d..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/factory/MockObjectFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.fluent.mocker.factory; - -import com.forte.util.mockbean.*; - -/** - * MockObject对象工厂 - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - * @date 2019/2/27 14:38 - */ -public class MockObjectFactory { - - /** - * 创建一个普通mock对象 - * @param mockBean - * @param - * @return - */ - public static MockObject createNormalObj(MockBean mockBean){ - return new MockNormalObject<>(mockBean); - } - - - /** - * 创建一个map类型的mock对象 - * @param mockMapBean - * @return - */ - public static MockMapObject createMapObj(MockMapBean mockMapBean){ - return new MockMapObject(mockMapBean); - } - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/factory/MockProxyHandlerFactory.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/factory/MockProxyHandlerFactory.java deleted file mode 100644 index 010df91..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/factory/MockProxyHandlerFactory.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.fluent.mocker.factory; - -import com.forte.util.mockbean.MockObject; - -import java.lang.reflect.InvocationHandler; -import java.util.function.BiFunction; - -/** - * Mock接口代理对象工厂的接口定义 - * @author ForteScarlet - */ -public interface MockProxyHandlerFactory { - - /** - * 获取代理处理接口{@link InvocationHandler}实例 - * @param mockObjectFunction 传入一个类型和一个可能为null的name字符串,获取一个mockObject对象。如果存在name,则会尝试先用name获取 - * @return JDK动态代理所需要的代理处理器示例。 - * @see InvocationHandler - */ - InvocationHandler getHandler(BiFunction, String, MockObject> mockObjectFunction); - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/factory/MockProxyHandlerFactoryImpl.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/factory/MockProxyHandlerFactoryImpl.java deleted file mode 100644 index d77a46c..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/factory/MockProxyHandlerFactoryImpl.java +++ /dev/null @@ -1,257 +0,0 @@ -package io.fluent.mocker.factory; - -import com.forte.util.mapper.MockProxy; -import com.forte.util.mapper.MockProxyType; -import com.forte.util.mockbean.MockObject; -import com.forte.util.utils.FieldUtils; - -import java.lang.invoke.MethodHandles; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.BiFunction; - -/** - * {@link MockProxyHandlerFactory}的默认实现 - * - * @author ForteScarlet - */ -public class MockProxyHandlerFactoryImpl implements MockProxyHandlerFactory { - - /** - * 获取接口代理处理器实例 - * 首先,只扫描所有的抽象方法,default方法不会代理,而是执行它自己。 - * - * @param mockObjectFunction 传入一个类型,获取一个mockObject对象。如果是Map类型,则第二参数为map的名称,否则忽视第二参数。 - * @return 接口代理处理器实例 - */ - @Override - public InvocationHandler getHandler(BiFunction, String, MockObject> mockObjectFunction) { - return new DefaultMockProxyHandler(mockObjectFunction); - } - - - /** - * 默认的mock接口代理处理器实现 - */ - public static class DefaultMockProxyHandler implements InvocationHandler { - - - /** - * mockObject获取器 - */ - private BiFunction, String, MockObject> mockObjectFunction; - - /** - * 方法返回值缓存map。 - */ - private Map> methodReturnCacheMap; - - /** - * 返回值永远为null的缓存值 - */ - private final SimpleBean nullValueCache = new SimpleBean<>((p, m, o) -> null); - - /** - * 构造需要一个mockObject获取器 - */ - public DefaultMockProxyHandler(BiFunction, String, MockObject> mockObjectFunction) { - this.mockObjectFunction = mockObjectFunction; - this.methodReturnCacheMap = new ConcurrentHashMap<>(2); - } - - /** - * 记录缓存 - */ - private void saveCache(Method m, InvocationHandler handler) { - methodReturnCacheMap.put(m, new SimpleBean<>(handler)); - } - - - /** - * 记录缓存 - */ - private void saveNullCache(Method m) { - methodReturnCacheMap.put(m, nullValueCache); - } - - - private InvocationHandler getCache(Method m) { - final SimpleBean supplierAtomicReference = methodReturnCacheMap.get(m); - return supplierAtomicReference == null ? null : supplierAtomicReference.get(); - } - - /** - * 函数接口 - * - * @param method 第一参数 - * @param args 第二参数 - * @return 返回值 - * @throws Throwable 任意异常 - */ - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - // 先尝试获取缓存 - final InvocationHandler cache = getCache(method); - if (cache != null) { - return cache.invoke(proxy, method, args); - } - - //如果是接口中的默认方法,使用特殊方法执行 - //代码源于网络: http://www.it1352.com/988865.html - if (method.isDefault()) { - Class declaringClass = method.getDeclaringClass(); - Constructor constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class); - constructor.setAccessible(true); - InvocationHandler defaultInvocationHandler = (p, m, o) -> constructor. - newInstance(declaringClass, MethodHandles.Lookup.PRIVATE). - unreflectSpecial(method, declaringClass). - bindTo(proxy). - invokeWithArguments(args); - - // 记录缓存 - saveCache(method, defaultInvocationHandler); - return defaultInvocationHandler.invoke(proxy, method, args); - } - - // 尝试获取@MockProxy注解 - final MockProxy mockProxyAnnotation = method.getAnnotation(MockProxy.class); - boolean ignore = mockProxyAnnotation != null && mockProxyAnnotation.ignore(); - // 返回值类型 - final Class returnType = method.getReturnType(); - - // 如果忽略此函数,则跳过 - if (ignore) { - return getDefaultResultAndCache(returnType, method); - } - - // 没有忽略,进行解析 - Class genericType = mockProxyAnnotation == null ? Object.class : mockProxyAnnotation.genericType(); - String name = mockProxyAnnotation == null ? null : mockProxyAnnotation.name().trim().length() == 0 ? null : mockProxyAnnotation.name().trim(); - int[] array = mockProxyAnnotation == null ? new int[]{1, 1} : mockProxyAnnotation.size(); - - // 准备参数 - MockProxyType proxyType = mockProxyAnnotation == null ? MockProxyType.UNKNOWN : mockProxyAnnotation.proxyType(); - // 如果是未知类型,根据返回值类型进行匹配。 - if(proxyType == MockProxyType.UNKNOWN){ - // 判断一下返回值的类型,如果是数组,转化为数组类型,如果是list,转化为list类型 - if(returnType.isArray()){ - final Class arrayComponentType = returnType.getComponentType(); - genericType = genericType.equals(Object.class) ? arrayComponentType : genericType; - proxyType = MockProxyType.ARRAY; - }else if(FieldUtils.isChild(returnType, List.class)){ - proxyType = MockProxyType.LIST; - }else{ - // 其他类型,认定为Object类型 - proxyType = MockProxyType.OBJECT; - } - } - - - if (array.length == 0) { - array = new int[]{1, 1}; - } - if (array.length == 1) { - array = new int[]{array[0], array[0]}; - } - if (array.length > 2) { - array = new int[]{array[0], array[1]}; - } - - - // 要获取的mock类型 - Class mockGetType = proxyType.selectTypeUse(returnType, genericType); - - - final MockObject mockObject = mockObjectFunction.apply(mockGetType, name); - - if (mockObject == null) { - // 获取不到mockObject, 获取默认返回值 - return getDefaultResultAndCache(returnType, method); - } - - // mockObject不为null,构建返回值 - - final int[] finalArr = array; - - final MockProxyType finalProxyType = proxyType; - - // 构建缓存函数 - InvocationHandler proxyHandler = (p, m, o) -> finalProxyType.buildReturnType(num -> { - if (num == 1) { - return new Object[]{mockObject.getOne()}; - } else if (num == 0) { - return new Object[0]; - } else if (num < 0) { - throw new IllegalArgumentException("size cannot be zero."); - } else { - return mockObject.getStream(num).toArray(Object[]::new); - } - }, mockGetType, finalArr[0], finalArr[1]); - - saveCache(method, proxyHandler); - return proxyHandler.invoke(proxy, method, args); - } - - /** - * 获取默认返回值并缓存 - * - * @param returnType 返回值类型 - * @param method 方法 - */ - private Object getDefaultResultAndCache(Class returnType, Method method) { - final Object defaultResult = getDefaultResult(returnType); - // 记录缓存 - if (defaultResult == null) { - saveNullCache(method); - } else { - InvocationHandler ignoreHandler = (p, m, o) -> defaultResult; - saveCache(method, ignoreHandler); - } - return defaultResult; - } - - - /** - * 获取默认返回值 - * - * @param returnType 返回值类型 - */ - private Object getDefaultResult(Class returnType) { - // char - if (returnType.equals(char.class)) { - return ' '; - } - // boolean - if (returnType.equals(boolean.class)) { - return false; - } - - // 浮点型 - Class[] basicFloatTypes = new Class[]{double.class, float.class}; - for (Class basicFloatType : basicFloatTypes) { - if (returnType.equals(basicFloatType)) { - return 0.0; - } - } - - // 整型 - Class[] basicNumberTypes = new Class[]{byte.class, short.class, int.class, long.class}; - for (Class basicNumberType : basicNumberTypes) { - if (returnType.equals(basicNumberType)) { - return 0; - } - } - - // 其他的返回null - return null; - } - - - } - - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/factory/SimpleBean.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/factory/SimpleBean.java deleted file mode 100644 index fa0113c..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/factory/SimpleBean.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.fluent.mocker.factory; - -import java.util.function.Supplier; - -/** - * 就是一个类的一层封装类 - * @author ForteScarlet - */ -public class SimpleBean implements Supplier { - - private T bean = null; - - public SimpleBean(){ } - public SimpleBean(T bean){ - this.bean = bean; - } - - public void set(T bean){ - this.bean = bean; - } - - /** - * Gets a result. - * @return a result - */ - @Override - public T get() { - return bean; - } -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/ArrayFieldValueGetter.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/ArrayFieldValueGetter.java deleted file mode 100644 index e099b72..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/ArrayFieldValueGetter.java +++ /dev/null @@ -1,238 +0,0 @@ -package io.fluent.mocker.fieldvaluegetter; - -import com.forte.util.exception.MockException; -import com.forte.util.invoker.Invoker; -import com.forte.util.utils.MethodUtil; -import com.forte.util.utils.RandomUtil; - -import javax.script.ScriptException; - -/** - * 数组类型的字段值获取器,与{@link ListFieldValueGetter}十分相似,基本可是说是只有参数类似不同了 - * - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -public class ArrayFieldValueGetter implements FieldValueGetter { - - /** - * 方法执行者们 - * 期望中 只有一个执行者 - * 不排除多个执行者的情况, - * 但是如果是多个执行者,List集合很大可能是String、Integer之类的基础数据类型 - */ - private final Invoker[] invokers; - - /** - * 区间参数,重复最终输出,参数期望中长度为2,0索引为最小值,1为最大值 - * 默认值为[1,1],即为不重复 - */ - private final Integer[] integerInterval; - - /** - * 多余字符 - * 集合字段的指令类参数中可能出现多余字符,当有多于字符的时候,list集合的类型有很大的概率是Sting、Integer之类的基础数据类型 - */ - private final String[] moreStrs; - - /** - * 获取一个数组 - * - * @return - */ - @Override - public Object[] value() { - //获取执行次数 - Integer min = integerInterval[0]; - Integer max = integerInterval[1]; - int num = (max == null ? min : RandomUtil.getNumberWithRight(min, max)); - //创建一个Object类型的List集合,用于保存数据 - Object[] list = new Object[num]; - //判断执行者的数量 - if (invokers.length > 1) { - - //当执行者数量大于1,执行方法 - getValueWhenInvokersMoreThan1(num, list); - - } else if (invokers.length <= 0) { - /* - * 没有执行者的情况,创建并返回一个空的字符串集合 - * 一般情况下不会出现空执行者的情况,就算是没有可执行方法也会有空值执行者 - */ - return new Object[0]; - } else { - - //当执行者的数量不大于1的时候,执行方法 - getValueWhenInvokerIs1(num, list); - } - //返回结果 - return list; - } - - /** - * 当执行者的数量超过1的时候 - * - * @param num - * @param list - */ - private void getValueWhenInvokersMoreThan1(int num, Object[] list) { - //执行者数量大于1的情况下,只能将全部执行结果的toString拼接,并尝试使用eval进行执行 - //如果eval可以执行,则保存eval中得到的结果,如果无法执行则返回拼接字符串 - StringBuilder sb = new StringBuilder(); - //开始遍历并执行 - try { - for (int i = 0; i < num; i++) { - //执行全部执行者 - for (int j = 0; j < invokers.length; j++) { - //如果有多余字符,先拼接多余字符 - if (moreStrs != null) { - sb.append(moreStrs[j]); - } - //拼接执行结果 - sb.append(invokers[j].invoke()); - } - //如果有多余字符且多余字符的数量比执行者多1 - //只要多余字符比执行者数量大,则说明多余字符的数量为执行者的数量+1 - if (moreStrs != null && moreStrs.length > invokers.length) { - //拼接多余字符的最后值 - sb.append(moreStrs[moreStrs.length - 1]); - } - String invokeStr = sb.toString(); - try { - //尝试使用eval进行执行 - Object eval = MethodUtil.eval(invokeStr); - //如果能执行成功,保存这个执行结果到集合 - list[i] = (eval); - } catch (ScriptException e) { - //如果执行失败,保存执行前的字符串 - list[i] = (invokeStr); - } - } - } catch (Exception e) { - throw new MockException(e); - } - } - - - /** - * 当执行者数量不大于1的时候 - * - * @param num - * @param list - */ - private void getValueWhenInvokerIs1(int num, Object[] list) { - - //执行者数量不大于1,即只有一个 - Invoker invoker = invokers[0]; - //尽管只有一个方法执行者,但是仍然可能存在多余字符 - //所以分两种情况 - //在有多余字符的情况下,处理方式类似于上面的多执行者 - if (moreStrs != null) { - //如果存在多余字符 - //准备拼接结果 - StringBuilder sb = new StringBuilder(); - //遍历num次数 - try { - for (int i = 0; i < num; i++) { - //先拼接多余字符,再拼接方法执行结果 - sb.append(moreStrs[i]); - //方法的执行结果 - sb.append(invoker.invoke()); - //如果多余字符有结尾,拼接 - //由于只有一个执行者,所以如果多余字符数量大于1就说明有尾部多余 - if (moreStrs.length > 1) { - //这里的元素索引不出意外的话,必定是2 - sb.append(moreStrs[moreStrs.length - 1]); - } - String invokeData = sb.toString(); - //尝试对结果进行eval - //如果执行成功,保存执行结果 - list[i] = (MethodUtil.evalCache(invokeData)); - } - } catch (Exception e) { - throw new MockException(e); - } - - } else { - //没有多余字符 - //只有一个方法执行者、且没有多余字符的情况是最稳定的情况。 - //指令参数类型情况下,这种类型只有及低的可能会出现类型异常(只要你的list类型没有填写错误) - //遍历num次数,执行执行者并将结果保存至list集合 - try { - for (int i = 0; i < num; i++) { - //执行结果 - list[i] = invoker.invoke(); - } - } catch (Exception e) { - throw new MockException(e); - } - } - } - - - /** - * 构造方法 - * - * @param invokers 方法执行者 - * @param integerInterval 区间参数 - * @param moreStrs 多余字符 - */ - public ArrayFieldValueGetter(Invoker[] invokers, Integer[] integerInterval, String[] moreStrs) { - this.invokers = invokers; - //如果多余字符长度为0,则赋值为null - this.moreStrs = moreStrs.length == 0 ? null : moreStrs; - //如果为true,则使用默认的数组 - boolean isNull = integerInterval == null || integerInterval.length > 2 || integerInterval[0] == null || integerInterval[1] == null; - if (isNull) { - this.integerInterval = new Integer[]{1, 1}; - } else { - this.integerInterval = integerInterval; - } - } - - /** - * 构造方法,区间参数默认为[1,1] - * - * @param invokers 方法执行者 - * @param moreStrs 多余字符 - */ - public ArrayFieldValueGetter(Invoker[] invokers, String[] moreStrs) { - this.invokers = invokers; - this.integerInterval = new Integer[]{1, 1}; - //如果多余字符长度为0,则赋值为null - this.moreStrs = moreStrs.length == 0 ? null : moreStrs; - } - - - /** - * 构造方法,没有多余字符 - * - * @param invokers 方法执行者 - * @param integerInterval 区间参数 - */ - public ArrayFieldValueGetter(Invoker[] invokers, Integer[] integerInterval) { - this.invokers = invokers; - //判断:数组为null || 长度大于2 || 左参数为null || 左右参数都为null - //如果为true,则使用默认的数组 - boolean isNull = integerInterval == null || integerInterval.length > 2 || integerInterval[0] == null || integerInterval[1] == null; - if (isNull) { - this.integerInterval = new Integer[]{1, 1}; - } else { - this.integerInterval = integerInterval; - } - //多余字符赋值为null - this.moreStrs = null; - } - - /** - * 构造方法,没有多余字符,区间参数默认为[1,1] - * - * @param invokers 方法执行者 - */ - public ArrayFieldValueGetter(Invoker[] invokers) { - this.invokers = invokers; - this.integerInterval = new Integer[]{1, 1}; - //多余字符赋值为null - this.moreStrs = null; - } - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/DoubleFieldValueGetter.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/DoubleFieldValueGetter.java deleted file mode 100644 index 9407eda..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/DoubleFieldValueGetter.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.fluent.mocker.fieldvaluegetter; - -import com.forte.util.exception.MockException; -import com.forte.util.invoker.Invoker; - - -/** - * Double类型字段值获取器 - * 既然使用了此字段值获取器,则说明已经确定了字段的类型,则必定不会出现多个执行者。 - * - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -public class DoubleFieldValueGetter implements FieldValueGetter { - - /** - * 方法执行者,用于获取double值 - * 方法执行者必定为1个 - */ - private Invoker invoker; - - @Override - public Double value() { - //直接返回执行结果 - try { - return (Double) invoker.invoke(); - } catch (Exception e) { - throw new MockException(e); - } - } - - - /** - * 构造方法,只需要一个方法执行者 - */ - public DoubleFieldValueGetter(Invoker invoker) { - this.invoker = invoker; - } - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/EnumFieldValueGetter.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/EnumFieldValueGetter.java deleted file mode 100644 index d64c824..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/EnumFieldValueGetter.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.fluent.mocker.fieldvaluegetter; - -/** - * - * 枚举类型的字段值获取器 - * - * @deprecated 尚未实现完成 - * - * @author ForteScarlet - * @date 2020/8/1 - */ -@Deprecated -public class EnumFieldValueGetter> implements FieldValueGetter> { - - @Override - public Enum value() { - return null; - } -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/FieldValueGetter.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/FieldValueGetter.java deleted file mode 100644 index 5fc533a..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/FieldValueGetter.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.fluent.mocker.fieldvaluegetter; - -/** - * 字段值获取器 - * - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -@FunctionalInterface -public interface FieldValueGetter { - - /** - * 获取这个字段的参数 - */ - T value(); - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/IntegerFieldValueGetter.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/IntegerFieldValueGetter.java deleted file mode 100644 index 1744926..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/IntegerFieldValueGetter.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.fluent.mocker.fieldvaluegetter; - -import com.forte.util.exception.MockException; -import com.forte.util.invoker.Invoker; - - -/** - * 整数类型字段值获取器 - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -public class IntegerFieldValueGetter implements FieldValueGetter { - - /** - * 方法执行者用于获取整数类型的字段值 - * 执行者必然只有一个 - */ - private Invoker invoker; - - - /** - * 获取一个整数类型的字段值 - * @return - */ - @Override - public Integer value() { - try { - return (Integer) invoker.invoke(); - } catch (Exception e) { - throw new MockException(e); - } - } - - - /** - * 构造方法,只需要一个方法执行者 - */ - public IntegerFieldValueGetter(Invoker invoker) { - this.invoker = invoker; - } - - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/ListFieldValueGetter.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/ListFieldValueGetter.java deleted file mode 100644 index 33ffa22..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/ListFieldValueGetter.java +++ /dev/null @@ -1,324 +0,0 @@ -package io.fluent.mocker.fieldvaluegetter; - -import com.forte.util.exception.MockException; -import com.forte.util.invoker.Invoker; -import com.forte.util.utils.MethodUtil; -import com.forte.util.utils.RandomUtil; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.ThreadLocalRandom; -import java.util.function.Supplier; - -/** - * List集合的字段值获取器 - * 有较大的可能出现一些类型异常,请注意一定按照规范填写 - * - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -public class ListFieldValueGetter implements FieldValueGetter { - - - /** - * 方法执行者们 - * 期望中 只有一个执行者 - * 不排除多个执行者的情况, - * 但是如果是多个执行者,List集合很大可能是String、Integer之类的基础数据类型 - */ - private final Invoker[] invokers; - - /** - * 区间参数,重复最终输出,参数期望中长度为2,0索引为最小值,1为最大值 - * 默认值为[1,1],即为不重复 - * - * @since 1.7.0 当前版本替换为获取函数 - */ - private final Supplier integerIntervalSupplier; - - /** - * 多余字符 - * 集合字段的指令类参数中可能出现多余字符,当有多于字符的时候,list集合的类型有很大的概率是Sting、Integer之类的基础数据类型 - */ - private final String[] moreStrs; - - - /** - * 获取字段值 - */ - @Override - public List value() { - Integer[] integerInterval = integerIntervalSupplier.get(); - //创建一个Object类型的List集合,用于保存数据 - List list = new ArrayList(); - //获取执行次数 - Integer min = integerInterval[0]; - Integer max = integerInterval[1]; - int num = (max == null ? min : RandomUtil.getNumberWithRight(min, max)); - //判断执行者的数量 - if (invokers.length > 1) { - - //当执行者数量大于1,执行方法 - getValueWhenInvokersMoreThan1(num, list); - - } else if (invokers.length <= 0) { - /* - * 没有执行者的情况,创建并返回一个空的字符串集合 - * 一般情况下不会出现空执行者的情况,就算是没有可执行方法也会有空值执行者 - */ -// return new ArrayList(); - return list; - } else { - - //当执行者的数量不大于1的时候,执行方法 - getValueWhenInvokerIs1(num, list); - } - //返回结果 - return list; - } - - /** - * 当执行者的数量超过1的时候 - * - * @param num - * @param list - */ - private void getValueWhenInvokersMoreThan1(int num, List list) { - //执行者数量大于1的情况下,只能将全部执行结果的toString拼接,并尝试使用eval进行执行 - //如果eval可以执行,则保存eval中得到的结果,如果无法执行则返回拼接字符串 - StringBuilder sb = new StringBuilder(); - //开始遍历并执行 - try { - for (int i = 0; i < num; i++) { - //执行全部执行者 - for (int j = 0; j < invokers.length; j++) { - //如果有多余字符,先拼接多余字符 - if (moreStrs != null) { - sb.append(moreStrs[j]); - } - //拼接执行结果 - sb.append(invokers[j].invoke()); - } - - //如果有多余字符且多余字符的数量比执行者多1 - //只要多余字符比执行者数量大,则说明多余字符的数量为执行者的数量+1 - if (moreStrs != null && moreStrs.length > invokers.length) { - //拼接多余字符的最后值 - sb.append(moreStrs[moreStrs.length - 1]); - } - String invokeStr = sb.toString(); - //尝试使用eval进行执行 - Object eval = MethodUtil.evalCache(invokeStr); - //如果能执行成功,保存这个执行结果到集合 - list.add(eval); - } - } catch (Exception e) { - throw new MockException(e); - } - } - - - /** - * 当执行者数量不大于1的时候 - * - * @param num - * @param list - */ - private void getValueWhenInvokerIs1(int num, List list) { - //执行者数量不大于1,即只有一个 - Invoker invoker = invokers[0]; - //尽管只有一个方法执行者,但是仍然可能存在多余字符 - //所以分两种情况 - //在有多余字符的情况下,处理方式类似于上面的多执行者 - if (moreStrs != null) { - //如果存在多余字符 - //准备拼接结果 - StringBuilder sb = new StringBuilder(); - //遍历num次数 - try { - for (int i = 0; i < num; i++) { - //先拼接多余字符,再拼接方法执行结果 - sb.append(moreStrs[i]); - //方法的执行结果 - sb.append(invoker.invoke()); - //如果多余字符有结尾,拼接 - //由于只有一个执行者,所以如果多余字符数量大于1就说明有尾部多余 - if (moreStrs.length > 1) { - //这里的元素索引不出意外的话,必定是2 - sb.append(moreStrs[moreStrs.length - 1]); - } - String invokeData = sb.toString(); - //尝试对结果进行eval - //如果执行成功,保存执行结果 - Object eval = MethodUtil.evalCache(invokeData); - list.add(eval); - } - } catch (Exception e) { - throw new MockException(e); - } - } else { - //没有多余字符 - //只有一个方法执行者、且没有多余字符的情况是最稳定的情况。 - //指令参数类型情况下,这种类型只有及低的可能会出现类型异常(只要你的list类型没有填写错误) - //遍历num次数,执行执行者并将结果保存至list集合 - try { - for (int i = 0; i < num; i++) { - //执行结果 - list.add(invoker.invoke()); - } - } catch (Exception e) { - throw new MockException(e); - //如果执行出现错误,保存一个空值 null -// list.add(null); - } - } - } - - - /** - * 获取一个固定值的区间获取函数 - * - * @param a 固定区间 a - * @param b 固定区间 b - */ - static Supplier normalIntegerIntervalSupplier(int a, int b) { - Integer[] intervalsNew = new Integer[]{a, b}; - return () -> intervalsNew; - } - - /** - * 获取一个固定值的区间获取函数 - * - * @param intervals 固定区间 - */ - static Supplier normalIntegerIntervalSupplier(Integer[] intervals) { - Integer[] intervalsNew = Arrays.copyOf(intervals, intervals.length); - return () -> intervalsNew; - } - - /** - * 根据两个区间来随机获取其中一个区间的函数 - * - * @param intervals1 第一个区间 - * @param intervals2 第二个区间 - * @return 获取函数 - */ - static Supplier normalIntegerIntervalSupplier(Integer[] intervals1, Integer[] intervals2) { - Integer[] intervals1New = Arrays.copyOf(intervals1, intervals1.length); - Integer[] intervals2New = Arrays.copyOf(intervals2, intervals2.length); - return () -> ThreadLocalRandom.current().nextBoolean() ? intervals1New : intervals2New; - } - - - /** - * 构造方法 - * - * @param invokers 方法执行者 - * @param integerInterval 区间参数 - * @param moreStrs 多余字符 - */ - public ListFieldValueGetter(Invoker[] invokers, Integer[] integerInterval, String[] moreStrs) { - this.invokers = invokers; - //如果多余字符长度为0,则赋值为null - this.moreStrs = moreStrs.length == 0 ? null : moreStrs; - //如果为true,则使用默认的数组 - boolean isNull = integerInterval == null || integerInterval.length > 2 || integerInterval[0] == null || integerInterval[1] == null; - if (isNull) { - this.integerIntervalSupplier = normalIntegerIntervalSupplier(1, 1); - } else { - this.integerIntervalSupplier = normalIntegerIntervalSupplier(integerInterval); - } - } - - /** - * 构造方法 - * - * @param invokers 方法执行者 - * @param integerInterval1 区间参数 - * @param integerInterval2 区间参数 - * @param moreStrs 多余字符 - */ - public ListFieldValueGetter(Invoker[] invokers, Integer[] integerInterval1, Integer[] integerInterval2, String[] moreStrs) { - this.invokers = invokers; - //如果多余字符长度为0,则赋值为null - this.moreStrs = moreStrs.length == 0 ? null : moreStrs; - //如果为true,则使用默认的数组 - boolean isNull1 = integerInterval1 == null || integerInterval1.length > 2 || integerInterval1[0] == null || integerInterval1[1] == null; - boolean isNull2 = integerInterval2 == null || integerInterval2.length > 2 || integerInterval2[0] == null || integerInterval2[1] == null; - - Integer[] integerInterval1New = isNull1 ? new Integer[]{1, 1} : integerInterval1; - Integer[] integerInterval2New = isNull2 ? integerInterval1New : integerInterval2; - - this.integerIntervalSupplier = normalIntegerIntervalSupplier(integerInterval1New, integerInterval2New); - } - - /** - * 构造方法,区间参数默认为[1,1] - * - * @param invokers 方法执行者 - * @param moreStrs 多余字符 - */ - public ListFieldValueGetter(Invoker[] invokers, String[] moreStrs) { - this.invokers = invokers; - this.integerIntervalSupplier = normalIntegerIntervalSupplier(1, 1); - //如果多余字符长度为0,则赋值为null - this.moreStrs = moreStrs.length == 0 ? null : moreStrs; - } - - /** - * 构造方法,没有多余字符 - * - * @param invokers 方法执行者 - * @param integerInterval 区间参数 - */ - public ListFieldValueGetter(Invoker[] invokers, Integer[] integerInterval) { - this.invokers = invokers; - //判断:数组为null || 长度大于2 || 左参数为null || 左右参数都为null - //如果为true,则使用默认的数组 - boolean isNull = integerInterval == null || integerInterval.length > 2 || integerInterval[0] == null || integerInterval[1] == null; - if (isNull) { - this.integerIntervalSupplier = normalIntegerIntervalSupplier(1, 1); - } else { - this.integerIntervalSupplier = normalIntegerIntervalSupplier(integerInterval); - } - //多余字符赋值为null - this.moreStrs = null; - } - - /** - * 构造方法,没有多余字符 - * - * @param invokers 方法执行者 - * @param integerInterval1 区间参数1 - * @param integerInterval2 区间参数2 - */ - public ListFieldValueGetter(Invoker[] invokers, Integer[] integerInterval1, Integer[] integerInterval2) { - this.invokers = invokers; - //判断:数组为null || 长度大于2 || 左参数为null || 左右参数都为null - //如果为true,则使用默认的数组 - boolean isNull1 = integerInterval1 == null || integerInterval1.length > 2 || integerInterval1[0] == null || integerInterval1[1] == null; - boolean isNull2 = integerInterval2 == null || integerInterval2.length > 2 || integerInterval2[0] == null || integerInterval2[1] == null; - - Integer[] integerInterval1New = isNull1 ? new Integer[]{1, 1} : integerInterval1; - Integer[] integerInterval2New = isNull2 ? integerInterval1New : integerInterval2; - - this.integerIntervalSupplier = normalIntegerIntervalSupplier(integerInterval1New, integerInterval2New); - - //多余字符赋值为null - this.moreStrs = null; - } - - /** - * 构造方法,没有多余字符,区间参数默认为[1,1] - * - * @param invokers 方法执行者 - */ - public ListFieldValueGetter(Invoker[] invokers) { - this.invokers = invokers; - this.integerIntervalSupplier = normalIntegerIntervalSupplier(1, 1); - //多余字符赋值为null - this.moreStrs = null; - } - - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/ObjectFieldValueGetter.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/ObjectFieldValueGetter.java deleted file mode 100644 index 90745ef..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/ObjectFieldValueGetter.java +++ /dev/null @@ -1,73 +0,0 @@ -package io.fluent.mocker.fieldvaluegetter; - -import com.forte.util.exception.MockException; -import com.forte.util.invoker.Invoker; -import com.forte.util.utils.MethodUtil; - -import javax.script.ScriptException; - -/** - * 字段类型为任意未知类型的时候 - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -public class ObjectFieldValueGetter implements FieldValueGetter { - - /** - * 方法执行者,期望值是只有一个,但是不能保证,假如有多个参数的话,尝试使用加法运算进行相加 - */ - private final Invoker[] invokers; - - /** - * 获取值 - * - * @return - */ - @Override - public Object value() { - try { - //如果只有一个执行者 - if (invokers.length > 1) { - //不止一个,拼接结果为类js代码并执行eval() - //用于执行eval的拼接字符串 - StringBuilder evalString = new StringBuilder(); - //用于防止执行出现错误的直接返回用的字符串 - StringBuilder returnString = new StringBuilder(); - //遍历执行并拼接 - for (int i = 0; i < invokers.length; i++) { - if (i != 0) { - evalString.append("+"); - } - //执行结果 - Object invoke = invokers[i].invoke(); - evalString.append(invoke); - returnString.append(invoke); - } - //遍历结束,执行加法运算并返回结果 - String forEval = evalString.toString(); - try { - return MethodUtil.eval(forEval); - } catch (ScriptException e) { - //如果出现异常,则直接返回结果的拼接字符串 - return returnString.toString(); - } - }else { - //直接返回执行结果 - return invokers[0].invoke(); - } - } catch (Exception e) { - //出现异常,抛出 - throw new MockException(e); - } - } - - - /** - * 构造方法 - * - * @param invokers 方法执行者 - */ - public ObjectFieldValueGetter(Invoker[] invokers) { - this.invokers = invokers; - } - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/StringFieldValueGetter.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/StringFieldValueGetter.java deleted file mode 100644 index 9e2e181..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/fieldvaluegetter/StringFieldValueGetter.java +++ /dev/null @@ -1,136 +0,0 @@ -package io.fluent.mocker.fieldvaluegetter; - - -import com.forte.util.exception.MockException; -import com.forte.util.invoker.Invoker; -import com.forte.util.utils.MethodUtil; -import com.forte.util.utils.RandomUtil; - -import java.util.Collections; -import java.util.function.Supplier; - -/** - * 字符串类型字段值的获取者 - * - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -public class StringFieldValueGetter implements FieldValueGetter { - - /** - * 方法执行者,顺序与解析出来的方法和多余字符之间的顺序一致 - */ - private final Invoker[] invokers; - - /** - * 多余字符,如果不为null,则长度必然是 方法执行者invokers 的数量的+1或者相同 - */ - private final String[] moreStr; - - /** - * 区间参数,重复最终输出,参数期望中长度为2,0索引为最小值,1为最大值 - * 默认值为[1,1],即为不重复 - */ - private final Integer[] integerInterval; - - - /** - * 获取重复次数的获取函数。 - */ - private final Supplier timeSupplier; - - - /** - * 获取字段值 - * - * @return - */ - @Override - public String value() { - StringBuilder sb = new StringBuilder(32); - //同时遍历方法与多余字符,使用methods遍历 - int i = 0; - int invokerLength = invokers.length; - try { - for (; i < invokerLength; i++) { - //如果有多余字符,先存多余字符,后存执行结果 - if (moreStr != null) { - sb.append(moreStr[i]); - } - - sb.append(invokers[i].invoke()); - } - } catch (Exception e) { - throw new MockException(e); - } - //如果多余字符不为空 - //判断多余字符的数量: - // 如果数量相等,说明在最后的方法后面没有多余参数, - // 如果数量多1,则说明在最后的方法后面还有多余字符 - //如果尾部有多余字符,添加 - if (moreStr != null && moreStr.length > invokerLength) { - sb.append(moreStr[i]); - } - - //重复输出,次数为integerInterval的参数 - //如果没有右参数,重复次数则为左参数 -// int times; - int times = timeSupplier.get(); -// if(integerInterval[1] == null){ -// times = integerInterval[0]; -// }else{ -// int min = integerInterval[0]; -// int max = integerInterval[1]; -// times = RandomUtil.getNumberWithRight(min , max); -// } - - //有些少数情况,end中拼接后的字符串是可以作为简单JS代码执行的,在此处重复字符串之前,尝试使用eval进行执行 - String end = String.valueOf(MethodUtil.evalCache(sb.toString())); - - - //重复次数并返回 - if (times <= 1) { - return end; - } else { - return String.join("", Collections.nCopies(times, end)); - } - } - - - /** - * 构造 - * - * @param invokers - * @param moreStr - */ - public StringFieldValueGetter(Invoker[] invokers, String[] moreStr, Integer[] integerInterval) { - this.invokers = invokers; - this.moreStr = moreStr; - //判断:数组为null || 长度大于2 || 左参数为null || 左右参数都为null - //如果为true,则使用默认的数组 - boolean isNull = integerInterval == null || integerInterval.length > 2 || integerInterval[0] == null || integerInterval[1] == null; - if (isNull) { - this.integerInterval = new Integer[]{1, 1}; - this.timeSupplier = () -> 1; - } else { - this.integerInterval = integerInterval; - int min = integerInterval[0]; - int max = integerInterval[1]; - this.timeSupplier = () -> RandomUtil.getNumberWithRight(min, max); - } - } - - /** - * 构造,区间参数默认为[1-1] - * - * @param invokers - * @param moreStr - */ - public StringFieldValueGetter(Invoker[] invokers, String[] moreStr) { - this.invokers = invokers; - this.moreStr = moreStr; - //区间为默认值 - this.integerInterval = new Integer[]{1, 1}; - this.timeSupplier = () -> 1; - } - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/function/ExFunction.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/function/ExFunction.java deleted file mode 100644 index a271ece..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/function/ExFunction.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.fluent.mocker.function; - -/** - * 三个参数的function - * @author ForteScarlet - */ -@FunctionalInterface -public interface ExFunction { - - /** - * 接收三个参数,返回一个结果 - */ - R apply(T t, U1 u1, U2 u2); -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/function/ExProxyHandler.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/function/ExProxyHandler.java deleted file mode 100644 index 9acf21c..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/function/ExProxyHandler.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.fluent.mocker.function; - -/** - * 带着异常处理的BiFunction,用于构建动态代理的参数 - */ -@FunctionalInterface -public interface ExProxyHandler { - /** - * 函数接口 - * - * @param t 第一参数 - * @param u 第二参数 - * @return 返回值 - * @throws Throwable 任意异常 - */ - R apply(T t, U u) throws Throwable; -} \ No newline at end of file diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/function/TypeParse.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/function/TypeParse.java deleted file mode 100644 index f00d707..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/function/TypeParse.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.fluent.mocker.function; - -import com.forte.util.parser.FieldParser; - -/** - * 用于{@link com.forte.util.parser.ParameterParser}中,来注册各种参数类型的解析器。 - * 参数类型一般代表的是Map中的这个Object - * @author ForteScarlet - */ -@FunctionalInterface -public interface TypeParse { - - /** - * 接收部分参数,得到一个解析结果 - * @param objectClass 封装类型 - * @param fieldName 字段名称 - * @param intervalStr 区间字符串 - * @param value 参数 - * @return 字段解析器 - */ - FieldParser parse(Class objectClass, String fieldName, String intervalStr, Object value); - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/invoker/ArrayElementInvoker.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/invoker/ArrayElementInvoker.java deleted file mode 100644 index b9dcab1..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/invoker/ArrayElementInvoker.java +++ /dev/null @@ -1,28 +0,0 @@ -package io.fluent.mocker.invoker; - -import com.forte.util.utils.RandomUtil; - -/** - * - * 数组类型的{@link ElementInvoker} - * - * @author ForteScarlet - * @date 2020/8/1 - */ -public class ArrayElementInvoker extends ElementInvoker { - - /** 集合参数 */ - private T[] arr; - /** - * 数组构造 - * @param arr - */ - public ArrayElementInvoker(T[] arr){ - this.arr = arr; - } - - @Override - public T getRandomElement() { - return RandomUtil.getRandomElement(arr); - } -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/invoker/ElementInvoker.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/invoker/ElementInvoker.java deleted file mode 100644 index 68cd251..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/invoker/ElementInvoker.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.fluent.mocker.invoker; - -import java.util.List; - -/** - * 随机元素值执行者 - * 两个字段,一个有值,一个为null - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - * @date 2018/12/7 20:37 - */ -public abstract class ElementInvoker implements Invoker { - - public abstract T getRandomElement(); - - /** - * 执行者,获取随机元素 - */ - @Override - public Object invoke() { - return getRandomElement(); - } - - public static ElementInvoker getInstance(T... array){ - return new ArrayElementInvoker<>(array); - } - - public static ElementInvoker getInstance(List list){ - return new ListElementInvoker<>(list); - } - - - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/invoker/Invoker.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/invoker/Invoker.java deleted file mode 100644 index 0c245d7..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/invoker/Invoker.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.fluent.mocker.invoker; - -/** - * 执行者接口,定义了一个执行者的函数,执行者会通过invoke()方法获得结果 - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -@FunctionalInterface -public interface Invoker { - - /** - * 返回方法执行的结果 - * @return 获取执行结果 - * @throws Exception 可能会存在异常 - */ - Object invoke() throws Exception; -} - diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/invoker/ListElementInvoker.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/invoker/ListElementInvoker.java deleted file mode 100644 index a6db384..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/invoker/ListElementInvoker.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.fluent.mocker.invoker; - -import com.forte.util.utils.RandomUtil; - -import java.util.List; - -/** - * - * list类型的{@link ElementInvoker} - * - * @author ForteScarlet - * @date 2020/8/1 - */ -public class ListElementInvoker extends ElementInvoker { - /** 集合参数 */ - private List list; - - - - /** - * 集合构造 - * @param list - */ - public ListElementInvoker(List list){ - this.list = list; - } - - @Override - public T getRandomElement() { - return RandomUtil.getRandomElement(list); - } -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/invoker/MethodInvoker.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/invoker/MethodInvoker.java deleted file mode 100644 index 310cba2..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/invoker/MethodInvoker.java +++ /dev/null @@ -1,101 +0,0 @@ -package io.fluent.mocker.invoker; - -import com.forte.util.utils.MethodUtil; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -/** - * 方法执行者,是{@link com.forte.util.invoker.Invoker}的是实现类,代表了一个方法的执行 - * - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -public class MethodInvoker implements Invoker { - /** - * 执行方法的对象 - */ - private final Object obj; - /** - * 方法的名字 - */ - private final String methodName; - /** - * 方法的参数 - */ - private final Object[] args; - /** - * 方法的主体 - MockUtil中的静态方法 - */ - private final Method method; - - /** - * 获取一个普通的{@link MethodInvoker} - * @param obj 实例 - * @param args 参数列表 - * @param method 方法实例 - * @return {@link MethodInvoker} - */ - public static MethodInvoker getInstance(Object obj, Object[] args, Method method){ - return new MethodInvoker(obj, args, method); - } - - /** - * 获取一个常量{@link MethodInvoker} - * @param constValue 常量值 - * @return {@link MethodInvoker} - */ - public static MethodInvoker getInstance(Object constValue){ - return new ConstValueMethodInvoker(constValue); - } - - /** - * 执行方法 - * - * @return - * @throws InvocationTargetException - * @throws IllegalAccessException - */ - @Override - public Object invoke() throws InvocationTargetException, IllegalAccessException { - // 普通的执行者 - return MethodUtil.invoke(obj, args, method); - } - - /** - * 构造 - */ - MethodInvoker(Object obj, Object[] args, Method method) { - this.obj = obj; - if(method != null){ - this.methodName = method.getName(); - }else{ - this.methodName = null; - } - this.args = args; - this.method = method; - } - - - /** - * 常量值方法执行者 - */ - static class ConstValueMethodInvoker extends MethodInvoker { - /** - * 如果是一个空执行者,将会将对象返回 - */ - private final Object constValue; - - ConstValueMethodInvoker(Object constValue){ - super(null, null, null); - this.constValue = constValue; - } - - /** - * 返回常量值 - */ - @Override - public Object invoke() { - return constValue; - } - } -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/BranchResult.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/BranchResult.java deleted file mode 100644 index 34af1ee..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/BranchResult.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.fluent.mocker.loader; - -/** - * 直译:分支结果 - * 代表结果有着成功与否 - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - * @date Created in 2018/12/26 17:53 - * @since JDK1.8 - **/ -public interface BranchResult extends Result { - - /** - * 判断是否成功 - * @return - */ - Boolean isSuccess(); - - /** - * 如果失败,为何失败 - * @return - */ - Exception why(); - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/DefaultMockMethodLoader.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/DefaultMockMethodLoader.java deleted file mode 100644 index 9cd72f2..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/DefaultMockMethodLoader.java +++ /dev/null @@ -1,369 +0,0 @@ -package io.fluent.mocker.loader; - -import com.forte.util.Mock; - -import java.lang.reflect.Method; -import java.util.*; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -/** - * 基础的假方法加载者 - * 加载的类或方法需要满足以下要求:
- *
    - *
  • 加载的方法不可与{@link com.forte.util.utils.MockUtil}中出现的方法发生方法名相同,参数数量也相同的情况,如果发生此情况,将会抛出异常。
  • - *
  • 方法必须有返回值(非void)
  • - *
- * ※ 本类目前不保证线程安全 - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - * @date Created in 2018/12/26 17:33 - * @since JDK1.8 - **/ -public class DefaultMockMethodLoader implements MethodLoader { - - /** 获取mock方法集,此时的方法集已经通过静态代码块初始化完毕 */ - private final Map MOCK_METHOD; - - /** 要加载的方法,方法不能重复,使用set */ - private Set waitingMethods = new HashSet<>(10); - - public DefaultMockMethodLoader(Map mockMethod){ - this.MOCK_METHOD = mockMethod; - } - - /** - * 根据方法名加载一个方法,如果方法名对应了多个方法,则会全部进行判断,因此可能会有多个方法 - * @param loadClz 指定类 - * @param methodName 方法名 - * @return 返回自身-链式 - */ - @Override - public MethodLoader append(Class loadClz, String methodName) { - //获取全部方法 - Method[] declaredMethods = loadClz.getDeclaredMethods(); - //返回结果 - return appends(Arrays.stream(declaredMethods).filter(m -> m.getName().equals(methodName)).toArray(Method[]::new)); - } - - /** - * 添加一个方法 - * @param method 要加载的方法 - * @return 返回自身-链式 - */ - @Override - public MethodLoader append(Method method) { - if(can(method)){ - this.waitingMethods.add(method); - } - return this; - } - - /** - * 加载多个方法 - * @param methods 要加载的方法列表 - * @return 返回自身-链式 - */ - @Override - public MethodLoader appends(Method... methods) { - //筛选,方法名匹配且参数类型 - Set q = Arrays.stream(methods).filter(this::can).collect(Collectors.toSet()); - //添加结果 - this.waitingMethods.addAll(q); - return this; - } - - /** - * 加载类中的全部方法 - * @param loadClz 加载方法的类 - * @return 返回自身-链式 - */ - @Override - public MethodLoader appendAll(Class loadClz) { - return appends(loadClz.getDeclaredMethods()); - } - - /** - * 根据方法名筛选方法筛选 - * @param loadClz 加载方法的类 - * @param predicate 匹配规则 - * @return 返回自身-链式 - */ - @Override - public MethodLoader appendForNameFilter(Class loadClz, Predicate predicate) { - //先根据方法名筛选过滤 - Method[] q = Arrays.stream(loadClz.getDeclaredMethods()).filter(m -> predicate.test(m.getName())).toArray(Method[]::new); - return appends(q); - } - - /** - * 根据方法筛选方法筛选 - * @param loadClz 加载方法的类 - * @param predicate 匹配规则 - * @return 返回自身-链式 - */ - @Override - public MethodLoader appendForMethodFilter(Class loadClz, Predicate predicate) { - //根据条件筛选 - Method[] q = Arrays.stream(loadClz.getDeclaredMethods()).filter(predicate).toArray(Method[]::new); - return appends(q); - } - - /** - * 加载指定方法名的多个方法 - * @param loadClz 加载方法的类 - * @param names 方法名列表 - * @return 返回自身-链式 - */ - @Override - public MethodLoader appendByNames(Class loadClz, String[] names) { - //遍历每个名字并尝试加载 - for (String name : names) { - append(loadClz , name); - } - return this; - } - - /** - * 加载指定方法名的多个方法 - * @param loadClz 加载方法的类 - * @param names 方法名列表 - * @return 返回自身-链式 - */ - @Override - public MethodLoader appendByNames(Class loadClz, List names) { - return appendByNames(loadClz , names.toArray(new String[0])); - } - - /** - * 根据正则规则匹配方法中的方法名 - * @param loadClz 加载方法的类 - * @param regex 正则表达式 - * @return 返回自身-链式 - */ - @Override - public MethodLoader appendByRegex(Class loadClz, String regex) { - return appendForNameFilter(loadClz, s -> s.matches(regex)); - } - - /** - * 过滤 - * @param predicate 过滤规则 - * @return 过滤后的结果 - */ - @Override - public MethodLoader filter(Predicate predicate) { - //过滤并重新赋值 - waitingMethods = waitingMethods.stream().filter(predicate).collect(Collectors.toSet()); - return this; - } - - - /* ———————————————————————— 非链式方法 —————————————————————— */ - - /** - * 加载某类中指定方法名的方法。如果有重载方法将会全部判断 - * - * @param loadClz 指定类 - * @param methodName 方法名 - * @return 处理结果 - */ - @Override - public LoadResults add(Class loadClz, String methodName) { - //获取全部方法 - Method[] declaredMethods = loadClz.getDeclaredMethods(); - //返回结果 - return adds(declaredMethods); - - } - - /** - * 加载指定方法 - * - * @param method 要加载的方法 - * @return 处理结果 - */ - @Override - public LoadResults add(Method method) { - //返回结果 - return adds(method); - } - - /** - * 直接加载方法 - * - * @param methods 要加载的方法列表 - * @return 处理结果 - */ - @Override - public LoadResults adds(Method... methods) { - //筛选,方法名匹配且参数类型 - Set q = Arrays.stream(methods).filter(this::can).collect(Collectors.toSet()); - - //直接添加方法 - return load(q); - } - - /** - * 加载class中的全部方法 - * - * @param loadClz 加载方法的类 - * @return 处理结果 - */ - @Override - public LoadResults addAll(Class loadClz) { - return adds(loadClz.getDeclaredMethods()); - } - - /** - * 根据匹配规则对类中的方法名进行过滤 - * - * @param loadClz 加载方法的类 - * @param predicate 匹配规则 - * @return 处理结果 - */ - @Override - public LoadResults addForNameFilter(Class loadClz, Predicate predicate) { - Method[] q = Arrays.stream(loadClz.getDeclaredMethods()).filter(m -> predicate.test(m.getName())).toArray(Method[]::new); - return adds(q); - } - - /** - * 根据匹配规则对类中的方法进行过滤 - * - * @param loadClz 加载方法的类 - * @param predicate 匹配规则 - * @return 处理结果 - */ - @Override - public LoadResults addForMethodFilter(Class loadClz, Predicate predicate) { - //根据条件筛选 - Method[] q = Arrays.stream(loadClz.getDeclaredMethods()).filter(predicate).toArray(Method[]::new); - return adds(q); - } - - /** - * 根据方法名列表加载class中的指定方法 - * - * @param loadClz 加载方法的类 - * @param names 方法名列表 - * @return 处理结果 - */ - @Override - public LoadResults addByNames(Class loadClz, String[] names) { - //根据名称获取全部方法 - Method[] methods = loadClz.getMethods(); - //将方法名匹配的方法留下 - Method[] endMethod = Arrays.stream(methods).filter(m -> Arrays.stream(names).anyMatch(n -> n.equals(m.getName()))).toArray(Method[]::new); - - //返回结果 - return adds(endMethod); - } - - /** - * 根据方法名列表加载class中的指定方法 - * - * @param loadClz 加载方法的类 - * @param names 方法名列表 - * @return 处理结果 - */ - @Override - public LoadResults addByNames(Class loadClz, List names) { - return addByNames(loadClz, names.toArray(new String[0])); - } - - /** - * 根据正则对方法名匹配并加载class中符合条件的方法 - * - * @param loadClz 加载方法的类 - * @param regex 正则表达式 - * @return 处理结果 - */ - @Override - public LoadResults addByRegex(Class loadClz, String regex) { - return addForNameFilter(loadClz , s -> s.matches(regex)); - } - - /* ———————————————————————— 终结方法 —————————————————————— */ - - /** - * 要加载的内容是否为空 - * @return 是否为空 - */ - @Override - public boolean isEmpty() { - return waitingMethods.isEmpty(); - } - - /** - * 加载 - * @return 加载结果 - */ - @Override - public LoadResults load() { - return load(waitingMethods); - } - - - /** - * 将传入的方法加载至随机方法集中并返回添加结果报告 - * @param methods - * @return - */ - private LoadResults load(Set methods){ - //遍历要加载的方法并添加,并获取结果返回值 - Set> collect = methods.stream().flatMap(m -> { - Map methodMap = new HashMap<>(8); - //格式化方法名,并作为key - String key = m.getName() + "(" - + Arrays.stream(m.getParameterTypes()) - .map(Class::getName) - .collect(Collectors.joining(",")) + - ")"; - methodMap.put(key, m); - - //添加记录 - MOCK_METHOD.put(key, m); - - return methodMap.entrySet().stream(); - }).map(e -> { - //遍历所有的Entry对象 - try { - Method put = Mock._getMockMethod().put(e.getKey(), e.getValue()); - //如果添加成功则保存 - return MockMethodLoadResult.success(put); - } catch (Exception err) { - //如果添加失败则返回错误 - return MockMethodLoadResult.fail(e.getValue(), err); - } - }).collect(Collectors.toSet()); - - //返回结果集封装 - return new MockMethodLoadReport(collect); - } - - - /* ———————————————————————— 部分getter的api —————————————————————— */ - - - /** - * 等待加载的方法集 - * - * @return - */ - @Override - public Set waiting() { - return waitingMethods; - } - - /** - * 等待加载的方法集的数量 - * - * @return - */ - @Override - public int waitingNum() { - return waitingMethods.size(); - } - - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/LoadResults.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/LoadResults.java deleted file mode 100644 index fe330ce..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/LoadResults.java +++ /dev/null @@ -1,45 +0,0 @@ -package io.fluent.mocker.loader; - -import java.lang.reflect.Method; -import java.util.Map; -import java.util.Set; - -/** - * 方法加载后的返回值接口 - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - * @date Created in 2018/12/26 17:40 - * @since JDK1.8 - **/ -public interface LoadResults { - - /** - * 将成功加载的结果返回 - * @return 成功结果 - */ - Set loadSuccessResults(); - - /** - * 将结果作为结果返回,分为成功和失败两种结果 - * @return - */ - Map> loadResults(); - - /** - * 成功结果的数量 - * @return - */ - int successNums(); - - /** - * 失败的结果数量 - * @return - */ - int failNums(); - - /** - * 将加载错误的方法返回,并告知其失败原因 - * @return - */ - Map whyFail(); - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/MethodLoader.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/MethodLoader.java deleted file mode 100644 index 68bdd5a..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/MethodLoader.java +++ /dev/null @@ -1,245 +0,0 @@ -package io.fluent.mocker.loader; - -import com.forte.util.Mock; - -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -/** - * 假方法加载类
- * 加载的类或方法需要满足以下要求:
- *
    - *
  • 加载的方法不可与{@link com.forte.util.utils.MockUtil}中出现的方法发生方法名相同,参数数量也相同的情况,如果发生此情况,将会抛出异常。
  • - *
  • 方法必须为有返回值的(非void)
  • - *
  • 方法如果存在参数,请使用引用数据类型,避免使用基本数据类型
  • - *
- * - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - * @date Created in 2018/12/24 20:36 - * @version 1.1 - * @since JDK1.8 - **/ -public interface MethodLoader { - - /* —————————————————————————— 预载单方法 —————————————————————————— */ - - /** - * 加载某类中指定方法名的方法。如果有重载方法将会全部判断 - * @param loadClz 指定类 - * @param methodName 方法名 - * @return 处理结果 - */ - MethodLoader append(Class loadClz , String methodName); - - /** - * 加载指定方法 - * @param method 要加载的方法 - * @return 处理结果 - */ - MethodLoader append(Method method); - - /* —————————————————————————— 预载多方法 —————————————————————————— */ - - /** - * 直接加载方法 - * @param methods 要加载的方法列表 - * @return 处理结果 - */ - MethodLoader appends(Method... methods); - - - /** - * 加载class中的全部方法 - * @param loadClz 加载方法的类 - * @return 处理结果 - */ - MethodLoader appendAll(Class loadClz); - - /** - * 根据匹配规则对类中的方法名进行过滤 - * @param loadClz 加载方法的类 - * @param predicate 匹配规则 - * @return 处理结果 - */ - MethodLoader appendForNameFilter(Class loadClz , Predicate predicate); - - /** - * 根据匹配规则对类中的方法进行过滤 - * @param loadClz 加载方法的类 - * @param predicate 匹配规则 - * @return 处理结果 - */ - MethodLoader appendForMethodFilter(Class loadClz , Predicate predicate); - - /** - * 根据方法名列表加载class中的指定方法 - * @param loadClz 加载方法的类 - * @param names 方法名列表 - * @return 处理结果 - */ - MethodLoader appendByNames(Class loadClz , String[] names); - - /** - * 根据方法名列表加载class中的指定方法 - * @param loadClz 加载方法的类 - * @param names 方法名列表 - * @return 处理结果 - */ - MethodLoader appendByNames(Class loadClz , List names); - - /** - * 根据正则对方法名匹配并加载class中符合条件的方法 - * @param loadClz 加载方法的类 - * @param regex 正则表达式 - * @return 处理结果 - */ - MethodLoader appendByRegex(Class loadClz , String regex); - - /* —————————————————————————— 数据处理 —————————————————————————— */ - - /** - * 对方法进行过滤 - * @param predicate 过滤规则 - * @return 处理结果 - */ - MethodLoader filter(Predicate predicate); - - - /** - * 判断此方法是否可行 - * @param method - * @return - */ - default boolean can(Method method){ - //如果此方法没有返回值则直接返回false - if(method.getReturnType().equals(void.class)){ - return false; - } - //获取已经加载的方法 - Map methodMap = Mock._getMockMethod(); - String keyName = method.getName() + "(" + Arrays.stream(method.getParameters()).map(p -> p.getType().getTypeName()).collect(Collectors.joining(",")) + ")"; - return methodMap.entrySet().stream().noneMatch( - e -> keyName.equals(e.getKey()) - && (method.getParameters().length == e.getValue().getParameters().length) - ); - } - - - - /* —————————————————————————— 加载/终结方法 —————————————————————————— */ - - - /** - * 将预载内容加载至方法集 - * @return 加载成功数量 - */ - LoadResults load(); - - - - /* —————————————————————————— 加载/终结方法-非链式 —————————————————————————— */ - - /* —————————————————————————— 预载单方法 —————————————————————————— */ - - /** - * 加载某类中指定方法名的方法。如果有重载方法将会全部判断 - * @param loadClz 指定类 - * @param methodName 方法名 - * @return 处理结果 - */ - LoadResults add(Class loadClz , String methodName); - - /** - * 加载指定方法 - * @param method 要加载的方法 - * @return 处理结果 - */ - LoadResults add(Method method); - - /* —————————————————————————— 预载多方法 —————————————————————————— */ - - /** - * 直接加载方法 - * @param methods 要加载的方法列表 - * @return 处理结果 - */ - LoadResults adds(Method... methods); - - - /** - * 加载class中的全部方法 - * @param loadClz 加载方法的类 - * @return 处理结果 - */ - LoadResults addAll(Class loadClz); - - /** - * 根据匹配规则对类中的方法名进行过滤 - * @param loadClz 加载方法的类 - * @param predicate 匹配规则 - * @return 处理结果 - */ - LoadResults addForNameFilter(Class loadClz , Predicate predicate); - - /** - * 根据匹配规则对类中的方法进行过滤 - * @param loadClz 加载方法的类 - * @param predicate 匹配规则 - * @return 处理结果 - */ - LoadResults addForMethodFilter(Class loadClz , Predicate predicate); - - /** - * 根据方法名列表加载class中的指定方法 - * @param loadClz 加载方法的类 - * @param names 方法名列表 - * @return 处理结果 - */ - LoadResults addByNames(Class loadClz , String[] names); - - /** - * 根据方法名列表加载class中的指定方法 - * @param loadClz 加载方法的类 - * @param names 方法名列表 - * @return 处理结果 - */ - LoadResults addByNames(Class loadClz , List names); - - /** - * 根据正则对方法名匹配并加载class中符合条件的方法 - * @param loadClz 加载方法的类 - * @param regex 正则表达式 - * @return 处理结果 - */ - LoadResults addByRegex(Class loadClz , String regex); - - /* —————————————————————————— 一些getter方法等api —————————————————————————— */ - - /** - * 等待加载的方法集 - * @return - */ - Set waiting(); - - /** - * 等待加载的方法集的数量 - * @return - */ - int waitingNum(); - - /** - * 判断预载内容是否为空 - * @return 判断结果 - */ - boolean isEmpty(); - - - - - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/MockMethodLoadReport.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/MockMethodLoadReport.java deleted file mode 100644 index 4b1ed25..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/MockMethodLoadReport.java +++ /dev/null @@ -1,79 +0,0 @@ -package io.fluent.mocker.loader; - -import java.lang.reflect.Method; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - * @date 2018/12/27 17:10 - */ -public class MockMethodLoadReport implements LoadResults { - - - private final Set> RESULTS; - - /** - * 将成功加载的结果返回 - * - * @return 成功结果 - */ - @Override - public Set loadSuccessResults() { - //获取成功的方法列表 - return RESULTS.stream().filter(BranchResult::isSuccess).map(BranchResult::getResult).collect(Collectors.toSet()); - } - - /** - * 将结果作为结果返回,分为成功和失败两种结果 - * @return - * 成功与否的结果集 - */ - @Override - public Map> loadResults() { - return RESULTS.stream().collect(Collectors.groupingBy( - BranchResult::isSuccess , - Collectors.mapping(BranchResult::getResult , Collectors.toSet()) - )); - } - - /** - * 成功结果的数量 - * @return - * 成功结果的数量 - */ - @Override - public int successNums() { - return (int) RESULTS.stream().filter(BranchResult::isSuccess).count(); - } - - /** - * 失败的结果数量 - * @return 失败的结果数量 - */ - @Override - public int failNums() { - return (int) RESULTS.stream().filter(r -> !r.isSuccess()).count(); - } - - /** - * 将加载错误的方法返回,并告知其失败原因 - * @return 错误的方法以及失败原因 - */ - @Override - public Map whyFail() { - return RESULTS.stream().filter(re -> !re.isSuccess()).collect(Collectors.toMap(BranchResult::getResult, BranchResult::why)); - } - - - - /** - * 构造 - * @param results 结果集 - */ - MockMethodLoadReport(Set> results){ - this.RESULTS = results; - } - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/MockMethodLoadResult.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/MockMethodLoadResult.java deleted file mode 100644 index 4c9df13..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/MockMethodLoadResult.java +++ /dev/null @@ -1,69 +0,0 @@ -package io.fluent.mocker.loader; - -import java.lang.reflect.Method; - -/** - * 方法的加载结果 - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - * @date Created in 2018/12/26 17:45 - * @since JDK1.8 - **/ -class MockMethodLoadResult implements BranchResult { - - /** 结果 */ - private final Method result; - - /** 如果结果为成功的结果,则为true */ - private final Boolean success; - - /** 如果success为false,则此字段记录的结果的失败原因(异常) */ - private final Exception why; - - - @Override - public Boolean isSuccess() { - return this.success; - } - - @Override - public Exception why() { - return this.why; - } - - @Override - public Method getResult() { - return this.result; - } - - /** - * 工厂方法。获得一个成功的返回值 - * @param result 结果 - * @return 返回一个实例 - */ - public static MockMethodLoadResult success(Method result){ - return new MockMethodLoadResult(result , true , null); - } - - /** - * 工厂方法。获得一个失败的返回值 - * @param result 结果 - * @param why 为何失败 - * @return 返回一个实例 - */ - public static MockMethodLoadResult fail(Method result , Exception why){ - return new MockMethodLoadResult(result , false, why); - } - - /** - * 唯一私有构造 - * @param result 结果 - * @param success 是否成功 - * @param why 为何失败 - */ - private MockMethodLoadResult(Method result, Boolean success, Exception why){ - this.result = result; - this.success = success; - this.why = why; - } - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/Result.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/Result.java deleted file mode 100644 index 7a1481a..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/loader/Result.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.fluent.mocker.loader; - -/** - * 方法的返回结果 - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - * @date Created in 2018/12/26 17:48 - * @since JDK1.8 - **/ -public interface Result { - - - /** - * 获取结果 - * @return 结果 - */ - T getResult(); - - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/ArrayMapper.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/ArrayMapper.java deleted file mode 100644 index 5d2a8fb..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/ArrayMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.fluent.mocker.mapper; - -import java.util.Arrays; -import java.util.function.Function; -import java.util.function.IntFunction; - -/** - * 映射器,可以指定将字符串数组内的值转化为其他类型 - * 需要存在一个无参构造 - * @author ForteScarlet <[email]ForteScarlet@163.com> - * @since JDK1.8 - **/ -public interface ArrayMapper extends Function { - - /** - * 给你一个数组长度,返回一个数组实例的function,用于数组的实例化获取 - * @return 数组实例获取函数 - */ - IntFunction getArrayParseFunction(); - - /** - * 进行转化, 将String类型的数组转化为某指定类型 - * @param array String array - */ - default T[] map(String[] array){ - //真正被使用的对外接口 - return Arrays.stream(array).map(this).toArray(this.getArrayParseFunction()); - } - - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/ArrayMapperType.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/ArrayMapperType.java deleted file mode 100644 index f13bdfd..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/ArrayMapperType.java +++ /dev/null @@ -1,94 +0,0 @@ -package io.fluent.mocker.mapper; - -import java.util.function.IntFunction; - -/** - * 部分指定好的转化器类型 - * 接口类型,内部提供部分ArrayMapper实现类 - * @author ForteScarlet <[email]ForteScarlet@163.com> - * @since JDK1.8 - **/ -public interface ArrayMapperType { - -// /** 转化为String类型 */ -// Class TO_STRING = ToString.class; -// -// /** 转化为Integer类型 */ -// Class TO_INT = ToInt.class; -// -// /** 转化为Double类型 */ -// Class TO_DOUBLE = ToDouble.class; -// -// /** 转化为Long类型 */ -// Class TO_LONG = ToLong.class; - - /** - * 保持String类型不变 - */ - class ToString implements ArrayMapper { - - @Override - public IntFunction getArrayParseFunction() { - return String[]::new; - } - - @Override - public String apply(String s) { - return s; - } - } - - /** - * 转化为Int类型 - */ - class ToInt implements ArrayMapper { - @Override - public Integer apply(String s) { - return Integer.parseInt(s); - } - @Override - public IntFunction getArrayParseFunction() { - return Integer[]::new; - } - } - - /** - * 转化为Double类型 - */ - class ToDouble implements ArrayMapper { - @Override - public IntFunction getArrayParseFunction() { - return Double[]::new; - } - - @Override - public Double apply(String s) { - return Double.parseDouble(s); - } - } - - /** - * 转化为Long类型 - */ - class ToLong implements ArrayMapper { - - @Override - public IntFunction getArrayParseFunction() { - return Long[]::new; - } - - @Override - public Long apply(String s) { - return Long.parseLong(s); - } - } - - - - - - - - - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/MockArray.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/MockArray.java deleted file mode 100644 index 89ef0c1..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/MockArray.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.fluent.mocker.mapper; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * 数组类型的注解,类型为整数类型, - * 可以指定一个转化规则使得这个字符串数组可以转化为其他类型 - * - * @author ForteScarlet <[email]ForteScarlet@163.com> - * @since JDK1.8 - **/ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) //字段 -public @interface MockArray { - - /** - * 数组参数 - */ - String[] value(); - - /** - * 类型转化器实现类,需要存在无参构造 - * 默认不变 - */ - Class mapper() default ArrayMapperType.ToString.class; - - - /** - * 区间参数,如果有值,则代表了字段之前的区间参数。默认没有值 - * 例如当字段{@code age} 的注解参数为 {@code param = "10-20"} 的时候, 相当于字段值为{@code "age|10-20"}。参数中的那个竖线不需要写。写了也会被去除的。 - * @since 1.6.0 - */ - String param() default ""; -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/MockBean.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/MockBean.java deleted file mode 100644 index 19e7423..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/MockBean.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.fluent.mocker.mapper; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 当进行包扫描的时候,会扫描到所有标记了此注解的类 - * 暂时没有参数,仅用作标记用。 - * @author ForteScarlet - */ -@Retention(RetentionPolicy.RUNTIME) //注解会在class字节码文件中存在,在运行时可以通过反射获取到 -@Target({ElementType.TYPE}) //类 -public @interface MockBean { -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/MockProxy.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/MockProxy.java deleted file mode 100644 index 517a10f..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/MockProxy.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.fluent.mocker.mapper; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Mock接口代理注解标识,标记在接口的抽象方法上。抽象方法 - * @author ForteScarlet - */ -@Retention(RetentionPolicy.RUNTIME) //注解会在class字节码文件中存在,在运行时可以通过反射获取到 -@Target({ElementType.METHOD}) //接口、类、枚举、注解、方法 -public @interface MockProxy { - - /** - *
 是否忽略此方法。如果为是,则接口的最终代理结果为返回一个null。
-     * 
 当然,如果获取不到对应的Mock类型,无论是否忽略都会返回null或者默认值。
-     * 
 如果是基础数据类型相关,数字类型,返回{@code 0}。
-     * 
 如果是基础数据类型相关,char类型,返回{@code ' '}。
-     * 
 如果是基础数据类型相关,boolean类型,返回{@code false}。
-     */
-    boolean ignore() default false;
-
-    /**
-     * 如果此参数存在值,则会优先尝试通过name获取MockObject对象
-     */
-    String name() default "";
-
-    /**
-     * 
 当接口返回值为数组或者集合的时候,此方法标记其返回值数量大小区间{@code [min, max], 即 max >= size >= min}。是数学上的闭区间。
-     * 
 如果此参数长度为0,则返回值为1。
-     * 
 如果参数长度为1,则相当于不是随机长度。
-     * 
 如果参数长度大于2,只取前两位。
-     */
-    int[] size() default {1,1};
-
-    /**
-     * 
 指定返回值类型,三种可能类型:list类型,array类型,Object其他任意类型。默认值为Unknown类型。当为Unknown类型的时候,会根据返回值类型自动判断。
-     * 
 当类型为list与array类型的时候,需要通过{@link #genericType()}方法指定泛型的类型,获取mock类型的时候将会通过此方法得到的类型来获取。
-     */
-    MockProxyType proxyType() default MockProxyType.UNKNOWN;
-
-
-    /**
-     * 假如类型为List类型,此处代表泛型的实际类型。
-     */
-    Class genericType() default Object.class;
-
-
-}
diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/MockProxyType.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/MockProxyType.java
deleted file mode 100644
index 54908e4..0000000
--- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/MockProxyType.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package io.fluent.mocker.mapper;
-
-import com.forte.util.exception.MockException;
-import com.forte.util.function.ExFunction;
-import com.forte.util.utils.RandomUtil;
-
-import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.function.BiFunction;
-import java.util.function.Function;
-
-/**
- * 代理接口对象的时候可能存在的三种类型:list类型,Array类型,和Object类型
- *
- * @author  ForteScarlet 
- */
-public enum MockProxyType {
-
-    /**
-     * 未知类型。直接使用此类型将会抛出异常。
-     * 但是一般来讲,默认的代理工厂内部会进行判断。
-     */
-    UNKNOWN(
-            (mrt, grt) -> {
-                throw new MockException("unknown proxy type.");
-            },
-            (f, num, t) -> {
-                throw new MockException("unknown proxy type.");
-            }
-    ),
-
-    /**
-     * 其他任意Object
-     * 返回值选择会选方法返回值
-     * 构建返回值的时候,无视区间参数,只会传入1且只取第一个返回值。
-     */
-    OBJECT(
-            (mrt, grt) -> mrt,
-            (f, num, t) -> f.apply(1)[0]
-    ) {
-        @Override
-        protected int getRandomNum(int min, int max) {
-            return 1;
-        }
-    },
-    /**
-     * 数组类型
-     */
-    ARRAY(
-            (mrt, grt) -> grt,
-            (f, num, t) -> {
-                final Object[] array = f.apply(num);
-                final Object newArrayInstance = Array.newInstance(t, array.length);
-                for (int i = 0; i < array.length; i++) {
-                    Array.set(newArrayInstance, i, array[i]);
-                }
-                return newArrayInstance;
-            }
-    ),
-    /**
-     * list类型
-     */
-    LIST(
-            (mrt, grt) -> grt,
-            (f, num, t) -> {
-                final Object[] array = f.apply(num);
-                return new ArrayList<>(Arrays.asList(array));
-            }
-    );
-
-    /**
-     * 函数参数1代表方法的返回值类型,参数2代表注解上的泛型类型(如果存在)
-     * 返回值代表使用哪个类型来获取泛型
-     */
-    private final BiFunction, Class, Class> selectUseTypeFunction;
-    /**
-     * 参数1代表一个函数,这个函数接收一个数量参数,返回一定数量的结果对象
-     * 参数2代表具体数量
-     * 参数3代表bean的类型
-     * 参数4代表最终的返回结果
-     */
-    private final ExFunction, Integer, Class, Object> resultObjectFunction;
-
-    MockProxyType(
-            BiFunction, Class, Class> selectUseTypeFunction,
-            ExFunction, Integer, Class, Object> resultObjectFunction
-    ) {
-        this.selectUseTypeFunction = selectUseTypeFunction;
-        this.resultObjectFunction = resultObjectFunction;
-    }
-
-    /**
-     * 选择使用的类型
-     *
-     * @param methodReturnType 方法类型
-     * @param genericType      泛型类型
-     * @return
-     */
-    public Class selectTypeUse(Class methodReturnType, Class genericType) {
-        return selectUseTypeFunction.apply(methodReturnType, genericType);
-    }
-
-    /**
-     * 根据函数构建最终结果
-     * @param beanGetter bean获取器
-     * @param beanType   bean的类型,即mock所得类型
-     * @param min
-     * @param max
-     * @return
-     */
-    public Object buildReturnType(Function beanGetter, Class beanType, int min, int max) {
-        final int randomNum = getRandomNum(min, max);
-        return resultObjectFunction.apply(beanGetter, randomNum, beanType);
-    }
-
-    protected int getRandomNum(int min, int max) {
-        return RandomUtil.getNumberWithRight(min, max);
-    }
-
-}
diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/MockValue.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/MockValue.java
deleted file mode 100644
index 5179859..0000000
--- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mapper/MockValue.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package io.fluent.mocker.mapper;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * 应用于注解映射, 使用在字段上
- * 映射值为字符串类型
- * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com>
- * @since JDK1.8
- **/
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD) //字段
-public @interface MockValue {
-
-    /**
-     * 映射值,如果为空则视为无效
-     */
-    String value();
-
-    /**
-     * 区间参数,如果有值,则代表了字段之前的区间参数。默认没有值
-     * 例如当字段{@code age} 的注解参数为 {@code param = "10-20"} 的时候, 相当于字段值为{@code "age|10-20"}。参数中的那个竖线不需要写。写了也会被去除的。
-     * @since  1.6.0
-     */
-    String param() default "";
-
-    /**
-     * 参数value的最终类型,在转化的时候会使用beanutils中的工具类{@link org.apache.commons.beanutils.ConvertUtils}进行类型转化, 默认为String类型。
-     * @return
-     */
-    Class valueType() default String.class;
-
-}
diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/ConstMockField.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/ConstMockField.java
deleted file mode 100644
index bf245f3..0000000
--- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/ConstMockField.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package io.fluent.mocker.mockbean;
-
-import com.forte.util.fieldvaluegetter.FieldValueGetter;
-
-/**
- * @author  ForteScarlet 
- */
-public class ConstMockField extends MockField {
-    /**
-     * 构造
-     * @param objType
-     * @param fieldName 字段名称
-     * @param fieldConstValue 字段值获取器
-     * @param fieldType 字段类型
-     */
-    public ConstMockField(Class objType, String fieldName, Object fieldConstValue, Class fieldType) {
-        super(objType, fieldName, () -> fieldConstValue, fieldType);
-    }
-}
diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/MockBean.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/MockBean.java
deleted file mode 100644
index 13e75b5..0000000
--- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/MockBean.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package io.fluent.mocker.mockbean;
-
-import com.forte.util.exception.MockException;
-
-import java.util.Arrays;
-
-/**
- * 假对象的封装类,利用此类的getObject来获取一个对象
- *
- * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com>
- */
-public class MockBean {
-
-    /**
-     * 需要封装假数据的对象
-     */
-    protected Class objectClass;
-
-    /**
-     * 假对象的全部字段
-     */
-    protected MockField[] fields;
-
-    /**
-     * 获取对象一个对象
-     * @return
-     */
-    public T getObject() {
-        //先创建一个实例
-        T instance;
-        try {
-            instance = getObjectClass().newInstance();
-        } catch (InstantiationException | IllegalAccessException e) {
-            return null;
-        }
-        for (MockField field : fields) {
-            try {
-                field.setValue(instance);
-            } catch (Exception e) {
-                // ignored ?
-                // no
-                throw new MockException(e);
-            }
-        }
-        //返回这个实例
-        return instance;
-    }
-
-    /**
-     * 获取假字段集
-     */
-    public MockField[] getFields(){
-        return Arrays.copyOf(fields, fields.length);
-    }
-
-
-    public Class getObjectClass(){
-        return objectClass;
-    }
-
-
-    public MockBean parallel(){
-        return new ParallelMockBean<>(objectClass, Arrays.copyOf(fields, fields.length));
-    }
-
-
-    public MockBean sequential(){
-        return this;
-    }
-
-
-
-
-    /**
-     * 构造方法
-     *
-     * @param objectClass
-     * @param fields
-     */
-    public MockBean(Class objectClass, MockField[] fields) {
-        this.objectClass = objectClass;
-        this.fields = fields;
-    }
-}
diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/MockField.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/MockField.java
deleted file mode 100644
index f78c4f7..0000000
--- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/MockField.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package io.fluent.mocker.mockbean;
-
-import com.forte.util.fieldvaluegetter.FieldValueGetter;
-import com.forte.util.utils.FieldUtils;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
-/**
- * 假字段值的字段封装对象的抽象类
- * 假的字段有几种类型:
- * 
    - *
  • 字符串
  • - *
  • 整数
  • - *
  • 浮点数
  • - *
  • 集合
  • - *
  • 数组
  • - *
  • 引用对象
  • - *
- * - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -public class MockField { - - private final Class objType; - - /** - * 字段值获取器 - */ - private FieldValueGetter valueGetter; - - /** - * 字段名称 - */ - private final String fieldName; - - /** - * 字段类型 - */ - private final Class fieldType; - - - private final Field field; - - - private final Method setterMethod; - - - - /** - * 为传入的对象的对应的参数赋值 - * 通过FieldUtils工具类使用setter方法赋值 - * @see FieldUtils - * - * @param - */ - public void setValue(Object bean) throws Exception { -// Object value = getValue(); -// if(setterMethod == null){ -// if(value.getClass().equals(fieldType)){ -// field.set(bean, value); -// }else{ -// field.set(bean, ConvertUtils.convert(value, fieldType)); -// } -// } - FieldUtils.objectSetter(bean, fieldName, getValue()); - } - - /** - * 获取字段的值 - * - * @return 字段的值 - */ - public Object getValue() { - return valueGetter.value(); - } - - /** - * 获取字段的名称 - * - * @return 字段名 - */ - public String getFieldName() { - return this.fieldName; - } - - - public Class getFieldType(){ - return this.fieldType; - } - - public Class getObjType() { - return objType; - } - - public FieldValueGetter getValueGetter() { - return valueGetter; - } - - public Field getField() { - return field; - } - - public Method getSetterMethod() { - return setterMethod; - } - - public void setValueGetter(FieldValueGetter valueGetter) { - this.valueGetter = valueGetter; - } - - /** - * 构造 - */ - public MockField(Class objType, String fieldName, FieldValueGetter fieldValueGetter, Class fieldType) { - this.objType = objType; - this.fieldName = fieldName; - this.valueGetter = fieldValueGetter; - this.fieldType = fieldType; - - // 获取field - if(objType != null){ - this.field = FieldUtils.getField(objType, fieldName); - this.field.setAccessible(true); - this.setterMethod = FieldUtils.getFieldSetter(objType, this.field); - }else{ - // 当类型为Map类型的时候,objType为null,因此field为null。 - this.field = null; - this.setterMethod = null; - } - - - - - - } - - @Override - public String toString() { - return "MockField(StringName='"+fieldName+"')"; - } -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/MockMapBean.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/MockMapBean.java deleted file mode 100644 index 398c440..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/MockMapBean.java +++ /dev/null @@ -1,61 +0,0 @@ -package io.fluent.mocker.mockbean; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.function.BinaryOperator; -import java.util.stream.Collectors; - -/** - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - * @date Created in 2019/2/14 16:52 - @since JDK1.8 - **/ -public class MockMapBean extends MockBean { - - - /** - * 重写MockBean的方法,返回Map封装对象 - * @return - */ - @Override - public Map getObject(){ - //假字段集 - MockField[] fields = this.getFields(); - - Map map = new LinkedHashMap<>(); - - for (MockField field : fields) { - map.merge(field.getFieldName(), field.getValue(), (old, val) -> throwingMerger()); - } - - return map; - -// return Arrays.stream(fields) -// .map(f -> new AbstractMap.SimpleEntry<>(f.getFieldName(), f.getValue())) -// .collect(Collectors.toMap( -// Map.Entry::getKey, Map.Entry::getValue, -// throwingMerger() , LinkedHashMap::new -// )); - } - - - /** - * 构造方法 - * - * @param fields - */ - public MockMapBean(MockField[] fields) { - super(Map.class, fields); - } - - /** - * 此方法来自 {@link Collectors#throwingMerger()} - * @param - * @return - */ - @SuppressWarnings("JavadocReference") - protected static BinaryOperator throwingMerger() { - return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); }; - } - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/MockMapObject.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/MockMapObject.java deleted file mode 100644 index ff3e3c3..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/MockMapObject.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.fluent.mocker.mockbean; - -import java.util.Map; - -/** - * - * Map类型的结果集合 - * - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - * @date 2019/2/27 14:39 - */ -public class MockMapObject implements MockObject { - - private final MockMapBean mockMapBean; - - @Override - public MockBean getMockBean() { - return mockMapBean; - } - -// /** -// * 返回获取结果的Optional封装类 -// * -// * @return -// */ -// @Override -// public Optional get() { -// return Optional.ofNullable(mockMapBean.getObject()); -// } - - /** - * - * @return - */ - @Override - public Map getOne() { - return mockMapBean.getObject(); - } - - /** - * 唯一构造 - * @param mockMapBean - */ - public MockMapObject(MockMapBean mockMapBean){ - this.mockMapBean = mockMapBean; - } - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/MockNormalObject.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/MockNormalObject.java deleted file mode 100644 index 65db972..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/MockNormalObject.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.fluent.mocker.mockbean; - -/** - * 将{@link MockBean}封装并返回 - * - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - * @date 2018/12/11 16:11 - * @since JDK1.8 - **/ -public class MockNormalObject implements MockObject { - - private final MockBean mockBean; - - @Override - public MockBean getMockBean() { - return mockBean; - } - -// /** -// * 返回获取结果的Optional封装类 -// * @return -// */ -// @Override -// public Optional get(){ -// return Optional.ofNullable(mockBean.getObject()); -// } - - @Override - public T getOne() { - return mockBean.getObject(); - } - - /** - * 唯一构造 - * @param mockBean - */ - public MockNormalObject(MockBean mockBean){ - this.mockBean = mockBean; - } -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/MockObject.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/MockObject.java deleted file mode 100644 index 8366deb..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/MockObject.java +++ /dev/null @@ -1,315 +0,0 @@ -package io.fluent.mocker.mockbean; - -import com.forte.util.utils.CollectorUtil; - -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collector; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -/** - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - * @date 2019/2/27 14:33 - */ -public interface MockObject { - - /** - * 获取一个MockBean对象 - */ - MockBean getMockBean(); - - - /** - * 返回获取结果的Optional封装类 - */ - default Optional get(){ - return Optional.ofNullable(getOne()); - } - - - /** - * 获取一个实例对象 - */ - T getOne(); - - - - /** - * 获取一个无限流 - */ - default Stream getStream(){ - return Stream.iterate(getOne(), i -> getOne()); - } - - /** - * 获取一个指定长度的流,等同于 getStream().limit(limit) - * @param limit - * @return - */ - default Stream getStream(int limit){ - return getStream().limit(limit); - } - - /** - * 获取一个并行无限流 - */ - default Stream getParallelStream(){ - return getStream().parallel(); - } - - /** - * 获取一个并行流 - */ - default Stream getParallelStream(int limit){ - return getParallelStream().limit(limit); - } - - /** - * 获取多个实例对象,作为list集合返回 - */ - default List getList(int num){ - ArrayList list = new ArrayList<>(num); - for (int i = 0; i < num; i++) { - list.add(getOne()); - } - return list; - } - - - /** - * 并行线程创建多个实例对象,作为list集合返回 - */ - default List getListParallel(int num){ - return collectParallel(num, Collectors.toList()); - } - - - /** - * 获取多个实例对象,根据转化规则转化后作为list集合返回 - * @param num - * @param mapper - * @param - * @return - */ - default List getList(int num , Function mapper){ - ArrayList list = new ArrayList<>(num); - for (int i = 0; i < num; i++) { - list.add(mapper.apply(getOne())); - } - return list; -// return collect(num, mapper, Collectors.toList()); - } - - - /** - * 获取多个实例对象,使用并行线程获取并根据指定规则进行转化,作为List返回 - * @param num - * @param mapper - * @param - * @return - */ - default List getListParallel(int num, Function mapper){ - return collectParallel(num, mapper, Collectors.toList()); - } - - - /** - * 获取多个实例对象,作为Set返回 - * @param num - * @return - */ - default Set getSet(int num){ - Set set = new LinkedHashSet<>((int) Math.ceil(num / 0.75)); - for (int i = 0; i < num; i++) { - set.add(getOne()); - } - return set; - } - - - /** - * 获取多个实例对象,使用并行流操作,作为Set返回 - * @param num - * @return - */ - default Set getSetParallel(int num){ - return collectParallel(num, Collectors.toSet()); - } - - - /** - * 获取多个实例对象,根据转化规则转化后作为Set返回 - */ - default Set getSet(int num , Function mapper){ - Set set = new LinkedHashSet<>((int) Math.ceil(num / 0.75)); - for (int i = 0; i < num; i++) { - set.add(mapper.apply(getOne())); - } - return set; - } - - - /** - * 获取多个实例对象,使用并行流根据转化规则进行转化后作为Set返回 - */ - default Set getSetParallel(int num, Function mapper){ - return collectParallel(num, mapper, Collectors.toSet()); - } - - - /** - * 获取多个实例对象,作为Map返回,需要指定Map的转化方式 - */ - default Map getMap(int num , Function keyMapper , Function valueMapper){ - Map map = new LinkedHashMap<>((int) Math.ceil(num / 0.75)); - for (int i = 0; i < num; i++) { - final T value = getOne(); - final K k = keyMapper.apply(value); - final V v = valueMapper.apply(value); - map.put(k, v); - } - return map; - } - - /** - * 获取多个实例对象,作为Map返回,需要指定Map的转化方式 - */ - default Map getMap(int num, Collector> collector){ - return collectToMap(num, collector); - } - - - /** - * 获取多个实例对象,作为Map返回,需要指定Map的转化方式 - */ - default Map getMapParallel(int num , Function keyMapper , Function valueMapper){ - return collectToMapParallel(num, keyMapper, valueMapper); - } - - /** - * 获取多个实例对象,作为Map返回,需要指定Map的转化方式 - */ - default Map getMapParallel(int num , Collector> collector){ - return collectToMapParallel(num, collector); - } - - - /** - * 串行collect - */ - default R collect(int num, Collector collector){ - return CollectorUtil.collector(num, this::getOne, collector); -// // 获取容器 -// A container = collector.supplier().get(); -// // 获取累加器 -// BiConsumer accumulator = collector.accumulator(); -// for (int i = 0; i < num; i++) { -// accumulator.accept(container, getOne()); -// } -// // 获取结果 -// return collector.finisher().apply(container); - // return getStream(num).collect(collector); - } - - /** - * 带转化的串行collect - */ - default N collect(int num, Function mapper, Collector collector){ - return CollectorUtil.collector(num, this::getOne, mapper, collector); - // return getStream(num).map(mapper).collect(collector); - } - - /** - * 串行collect toMap - */ - default Map collectToMap(int num, Collector> collector){ - return CollectorUtil.collector(num, this::getOne, collector); -// return getStream(num).collect(collector); - } - - /** - * 串行collect toMap - * 默认使用{@link LinkedHashMap} - */ - default Map collectToMap(int num, Function keyFunction, Function valueFunction){ - Map map = new LinkedHashMap<>(); - T one; - for (int i = 0; i < num; i++) { - one = getOne(); - map.put(keyFunction.apply(one), valueFunction.apply(one)); - } - return map; - // return getStream(num).collect(Collectors.toMap(keyFunction, valueFunction)); - } - - /** - * 带转化的串行collect toMap - * 默认使用{@link LinkedHashMap} - */ - default Map collectToMap(int num, Function mapper, Collector> collector){ - return CollectorUtil.collector(num, this::getOne, mapper, collector); - // return getStream(num).map(mapper).collect(collector); - } - - /** - * 带转化的collect toMap - * 默认使用{@link LinkedHashMap} - */ - default Map collectToMap(int num, Function mapper, Function keyFunction, Function valueFunction){ - Map map = new LinkedHashMap<>(); - T one; - for (int i = 0; i < num; i++) { - one = getOne(); - map.put(keyFunction.apply(mapper.apply(one)), valueFunction.apply(mapper.apply(one))); - } - return map; - // return getStream(num).map(mapper).collect(Collectors.toMap(keyFunction, valueFunction)); - } - - - /** - * 并行collect - */ - default R collectParallel(int num, Collector collector){ - return IntStream.range(0, num).parallel().mapToObj(i -> getOne()).collect(collector); - } - - /** - * 带转化的并行collect - */ - default N collectParallel(int num, Function mapper, Collector collector){ - return IntStream.range(0, num).parallel().mapToObj(i -> mapper.apply(getOne())).collect(collector); - } - - /** - * 并行collect - */ - default Map collectToMapParallel(int num, Collector> collector){ - return IntStream.range(0, num).parallel().mapToObj(i -> getOne()).collect(collector); - } - - /** - * 并行collect - */ - default Map collectToMapParallel(int num, Function keyFunction, Function valueFunction){ - return IntStream.range(0, num).parallel().mapToObj(i -> getOne()).collect(Collectors.toMap(keyFunction, valueFunction)); - } - - /** - * 带转化的并行collect - */ - default Map collectToMapParallel(int num, Function mapper, Collector> collector){ - return IntStream.range(0, num).parallel().mapToObj(i -> mapper.apply(getOne())).collect(collector); - } - - /** - * 带转化的并行collect - */ - default Map collectToMapParallel(int num, Function mapper, Function keyFunction, Function valueFunction){ - return IntStream.range(0, num).parallel().mapToObj(i -> mapper.apply(getOne())).collect(Collectors.toMap(keyFunction, valueFunction)); - } - - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/ParallelMockBean.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/ParallelMockBean.java deleted file mode 100644 index 449d2eb..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/ParallelMockBean.java +++ /dev/null @@ -1,55 +0,0 @@ -package io.fluent.mocker.mockbean; - -import com.forte.util.exception.MockException; - -import java.util.Arrays; - -/** - * @author ForteScarlet - * @date 2020/7/29 - */ -public class ParallelMockBean extends MockBean { - - - /** - * 获取对象一个对象 - * @return - */ - public T getObject() { - //先创建一个实例 - T instance; - try { - instance = objectClass.newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - return null; - } - Arrays.stream(fields).parallel().forEach(field -> { - try { - field.setValue(instance); - } catch (Exception e) { - // ignored ? - throw new MockException(e); - } - }); - //返回这个实例 - return instance; - } - - - public MockBean parallel(){ - return this; - } - - - public MockBean sequential(){ - return new MockBean<>(objectClass, Arrays.copyOf(fields, fields.length)); - } - - - /** - * 构造方法 - */ - public ParallelMockBean(Class objectClass, MockField[] fields) { - super(objectClass, fields); - } -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/ParallelMockMapBean.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/ParallelMockMapBean.java deleted file mode 100644 index 4341af1..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/mockbean/ParallelMockMapBean.java +++ /dev/null @@ -1,50 +0,0 @@ -package io.fluent.mocker.mockbean; - -import java.util.AbstractMap; -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * @author ForteScarlet - * @date 2020/7/29 - */ -public class ParallelMockMapBean extends MockMapBean { - - /** - * 重写MockBean的方法,返回Map封装对象 - * @return - */ - @Override - public Map getObject(){ - //假字段集 - MockField[] fields = this.getFields(); - - return Arrays.stream(fields).parallel() - .map(f -> new AbstractMap.SimpleEntry<>(f.getFieldName(), f.getValue())) - .collect(Collectors.toMap( - Map.Entry::getKey, Map.Entry::getValue, - throwingMerger() , LinkedHashMap::new - )); - } - - - public MockMapBean parallel(){ - return this; - } - - - public MockMapBean sequential(){ - return new MockMapBean(Arrays.copyOf(fields, fields.length)); - } - - /** - * 构造方法 - * - * @param fields - */ - public ParallelMockMapBean(MockField[] fields) { - super(fields); - } -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/package-info.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/package-info.java deleted file mode 100644 index ef28ed2..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/package-info.java +++ /dev/null @@ -1,13 +0,0 @@ -/** - * - *

- * 除了所有的工具类以外唯一的对外接口: {@link com.forte.util.Mock} - *

- *

- * 可用在参数映射的方法列表: {@link com.forte.util.utils.MockUtil} - *

- * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - * @date 2018/12/11 15:20 - * @since JDK1.8 - **/ -package io.fluent.mocker; \ No newline at end of file diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/ArraysParser.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/ArraysParser.java deleted file mode 100644 index 226a6ed..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/ArraysParser.java +++ /dev/null @@ -1,128 +0,0 @@ -package io.fluent.mocker.parser; - -import com.forte.util.fieldvaluegetter.FieldValueGetter; -import com.forte.util.invoker.Invoker; -import com.forte.util.utils.MethodUtil; - -import java.util.Arrays; -import java.util.Optional; - -/** - * 数组参数解析器 - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -class ArraysParser extends BaseFieldParser { - - /** 参数传入的数组 */ - private final Object[] defaultArr; - - /** - * 当字段类型既不是集合也不是数组的解析 - * 说明从参数中随机获取一个并返回 - * - * @return - */ - @Override - public FieldValueGetter parserForNotListOrArrayFieldValueGetter() { - //创建一个数组元素获取执行者 - Invoker invoker = MethodUtil.createArrayElementInvoker(defaultArr); - return getObjectFieldValueGetter(invoker); - } - - /** - * 当字段是一个list类型集合的时候 - * @return - */ - @Override - public FieldValueGetter parserForListFieldValueGetter() { - //转化并返回结果 - return getListFieldValueGetter(); - } - - - /** - * 当字段是一个数组类型的时候 - * @return - */ - @Override - public FieldValueGetter parserForArrayFieldValueGetter() { - //转化并返回结果 - return getArrayFieldValueGetter(); - } - - - /** - * 获取数组字段值获取器 - * @return - */ - private FieldValueGetter getArrayFieldValueGetter(){ - //获取随机元素值执行者 - Invoker invoker = MethodUtil.createArrayElementInvoker(defaultArr); - //因为区间不可能为null,直接转化并返回 - return Optional.of(getIntervalData()).map(i -> { - //如果有区间参数,根据区间参数获取字段值获取器 - return getArrayFieldValueGetter(new Invoker[]{invoker}, i); - }).get(); - } - - /** - * 获取集合字段值获取器 - * @return - */ - private FieldValueGetter getListFieldValueGetter(){ - //获取随机元素值执行者 - Invoker invoker = MethodUtil.createArrayElementInvoker(defaultArr); - //因为区间不可能为null,直接转化并返回 - return Optional.of(getIntervalData()).map(i -> { - //如果有区间参数,根据区间参数获取字段值获取器 - return getListFieldValueGetter(new Invoker[]{invoker}, i); - }).get(); - } - - - - /** - * 获取区间参数区间,如果没有区间参数则返回区间[1,1] - * @return - */ - private Integer[] getIntervalData(){ - //获取参数 - Integer min = intervalMin; - Integer max = intervalMax; - - //判断区间参数 - if(min == null){ - //如果没左参数 - if(max == null){ - //如果右参数也没有,直接返回一个[1,1]的区间 - return new Integer[]{1,1}; - }else{ - //如果有右参数,参数同化 - min = max; - } - }else{ - //有左参数,判断右参数 - if(max == null){ - //没有右参数,同化 - max = min; - } - //否则都有,不变 - } - //返回结果 - return new Integer[]{min ,max}; - } - - - /** - * 构造 - * - * @param objectClass - * @param fieldName - * @param intervalStr - */ - public ArraysParser(Class objectClass, String fieldName, String intervalStr, Object[] defaultArr) { - super(objectClass, fieldName, intervalStr); - //参数数组,复制一份而并非使用原来的 ->浅拷贝 - this.defaultArr = Arrays.copyOf(defaultArr, defaultArr.length); - } -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/BaseFieldParser.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/BaseFieldParser.java deleted file mode 100644 index 0ede773..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/BaseFieldParser.java +++ /dev/null @@ -1,936 +0,0 @@ -package io.fluent.mocker.parser; - -import com.forte.util.Mock; -import com.forte.util.fieldvaluegetter.*; -import com.forte.util.invoker.Invoker; -import com.forte.util.mockbean.MockField; -import com.forte.util.utils.FieldUtils; -import com.forte.util.utils.MethodUtil; -import com.forte.util.utils.RegexUtil; - -import java.lang.reflect.Method; -import java.util.*; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -/** - * 所有字段解析器的抽象父类
- *
- *
- *
- * 每一个字段都有可能是集合或者数组类型的,但是每种类型的参数解析结果却又不同
- * - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -public abstract class BaseFieldParser implements FieldParser { - - /** - * 类的class对象 - */ - protected final Class objectClass; - - /** - * 字段名称 - */ - protected final String fieldName; - - /** - * 区间参数字符串min-max - */ - protected final Integer intervalMin, intervalMax; - - /** - * 区间参数字符串-小数位min-max(如果有的话) - */ - protected final Integer intervalDoubleMin, intervalDoubleMax; - - /** - * 此字段的class类型 - */ - protected final Class fieldClass; - - /** - * 获取一个封装好的MockField对象 - * 不可重写 - * @return 封装好的MockField对象 - */ - @Override - public final MockField getMockField(){ - //解析获取字段值获取器 - FieldValueGetter fieldValueGetter = parserForFieldValueGetter(); - - //创建一个MockField对象并返回 - return new MockField(objectClass, fieldName, fieldValueGetter, getFieldClass()); - } - - /** - * 获取字段类型值 - */ - protected Class getFieldClass(){ - return fieldClass; - } - - /** - * 进行解析,判断需要产生的字段类型 - */ - private FieldValueGetter parserForFieldValueGetter() { - //字段值获取器 - FieldValueGetter fieldValueGetter; - //判断这个字段的类型是不是List集合的形式 - //根据字段的class对象判断类型 - boolean isList = FieldUtils.isChild(fieldClass, List.class); - //如果是list集合类型 - if (isList) { - //是list集合形式的解析 - fieldValueGetter = parserForListFieldValueGetter(); - - } else if (fieldClass.isArray()) { - //是Array数组的解析 - fieldValueGetter = parserForArrayFieldValueGetter(); - - } else { - //不是list集合形式或Array数组的解析 - fieldValueGetter = parserForNotListOrArrayFieldValueGetter(); - } - - //返回结果 - return fieldValueGetter; - } - - - - /* * * —————————————— 为子类服务的辅助方法 —————————————— * * */ - - - /* —————————————— 正则与方法的解析 ———————————————— */ - - /** - * 看看有没有匹配的方法 - * - * @param name 方法名 - * @return 是否有 - */ - protected static boolean match(String name) { - //获取正则 - String regex = ".*" + getMethodRegex() + ".*"; - return name.matches(regex); - } - - /** - * 获取匹配的方法 - * @param name 方法名 - * @return 匹配的方法合集 - */ - protected static String[] getMethods(String name) { - //获取正则 - String regex = getMethodRegex(); - return RegexUtil.getMatcher(name, regex).toArray(new String[0]); - } - - /** - * 获取对匹配的方法进行切割之后的结果 - * - * @return - */ - protected static String[] getMethodsSplit(String name) { - //获取正则 - String regex = getMethodRegex(); - return name.split(regex); - } - - - /** - * 获取一个方法执行者 - * @param methodName - * @return - */ - protected static Invoker getOneMethodInvoker(String methodName){ - return getMethodInvoker(new String[]{methodName}).get(0); - } - - - private static final Pattern replaceForNameRegex = - Pattern.compile("@|(\\(\\))|(\\(((\\w+)|('.+')|(\".+\"))(\\, *((\\w+)|('.+')|(\".+\")))*\\))"); - -// /** -// * 为方法{@link #getMethodInvoker}服务,提供正则来获取方法名 -// * @return -// */ -// private static String getReplaceForNameRegex(){ -// return "@|(\\(\\))|(\\(((\\w+)|('.+')|(\".+\"))(\\,((\\w+)|('.+')|(\".+\")))*\\))"; -// } - /** - * 为方法{@link #getMethodInvoker}服务,提供正则来获取方法名 - * @return - */ - private static Pattern getReplaceForNameRegex(){ - return replaceForNameRegex; - } - - /** - * 解析方法字符串并获取方法执行者 - * @param methods - * 方法名列表 - * @return - */ - protected static List getMethodInvoker(String[] methods) { - //移除@符号、空括号、一个参数的括号、两个参数的括号 -// String replaceForNameRegex = "@|(\\(\\))|(\\(\\w+(\\,\\w+)*\\))"; - Pattern replaceForNameRegex = getReplaceForNameRegex(); -// String replaceForParamRegex = "[(@" + getMethodNameRegexs() + ")\\(\\)]"; -// String regex = "@" + getMethodNameRegexs() + "(((\\((\\w+|\\w+\\,\\w+)\\))|(\\(\\))|())?)"; - - List invokerList = new ArrayList<>(); - - //遍历方法,保证顺序 - for (String methodStr : methods) { - //获取方法名称 - String methodName; -// String methodName = replaceForNameRegex.matcher(methodStr).replaceAll(""); -// String methodName = methodStr.replaceAll(replaceForNameRegex, ""); - - - int head = 0; - int end = -1; - if(methodStr.charAt(0) == '@'){ - head = 1; - } - end = methodStr.indexOf("("); - if(end > -1){ - methodName = methodStr.substring(head, end); - }else { - methodName = methodStr.substring(head); - } - -// System.out.println(methodStr); -// System.out.println(methodName); - - //获取方法的参数 - String[] params = getMethodParams(methodStr); - //获取方法对象 - Method method = getMethodFromName(methodName, params.length); - //返回一个方法执行者,如果为没有对应的方法则创建一个空执行者,返回原本的字符串 - if (method == null) { - invokerList.add(MethodUtil.createNullMethodInvoker(methodStr)); - } else { - invokerList.add(MethodUtil.createMethodInvoker(null, params, method)); - } - } - - //返回方法执行者的集合 - return invokerList; - } - - - /** - * 获取匹配MockUtil中的方法的正则 - * - * @return - */ - protected static String getMethodRegex() { - String collect = getMethodNameRegexs(); - //全数量参数匹配、参数间空格匹配(参数为任意字符匹配)- 有bug -// String regex = "(@"+ collect +"+((\\((.+(\\,.+)*)\\))|(\\(\\))|()|))"; - //全数量参数匹配、参数\\w匹配 -// String regex = "(@" + collect + "+((\\((\\w+(\\,\\w+)*)\\))|(\\(\\))|())?)"; - - //尝试支持中文字符串 - String regex = "(@" + collect + "{1}((\\((((\\w)+|('.+')|(\".+\"))(\\, *((\\w)+|('.+')|(\".+\")))*)\\))|(\\(\\))|())?)"; - - //值匹配0-1-2个参数 -// String regex = "(@"+ collect +"+((\\((\\w+|\\w+\\,\\w+)\\))|(\\(\\))|())?)"; - return regex; - } - - - /** - * 从方法字符串中获取参数 - * @param methodStr 方法字符串 - * @return - */ - public static String[] getMethodParams(String methodStr) { - String replaceForParamRegex = "(@" + getMethodNameRegexs() + ")|\\(|\\)"; - String[] split = methodStr.replaceAll(replaceForParamRegex, "").split("( *)\\,( *)"); - return Arrays.stream(split).map(s -> s.trim().replaceAll("['\"]", "")).filter(s -> s.length() > 0).toArray(String[]::new); - } - - /** - * 通过名称获取方法 - * @param methodName 纯方法名称 - * @param paramsLength 参数数量 - * @return MockUtil中对应方法名与参数数量的方法对象,如果没有获取到则返回null - */ - public static Method getMethodFromName(String methodName, int paramsLength) { - //过滤出方法名匹配,参数长度也匹配的方法 - Method value = null; - -// try { - Map.Entry mockMethod = Mock.getMockMethodByFilter(entry -> -// entry.getKey().replaceAll("\\([\\w\\.\\,]*\\)", "").equals(methodName) - entry.getKey().startsWith(methodName) - && entry.getValue().getParameters().length == paramsLength); - if(mockMethod != null){ - value = mockMethod.getValue(); - } -// //取值,理论上来说最后的过滤结果应该只有一个结果 -// value = Mock.getMockMethods().entrySet().stream() -// .filter(e -> e.getKey().replaceAll("\\([\\w\\.\\,]*\\)","").equals(methodName) && e.getValue().getParameters().length == paramsLength).findFirst().get().getValue(); -// } catch (NoSuchElementException e) { -// } - - //返回结果 - return value; - } - - -// private static final Pattern allMethodNameRegex; - - /** - * 获取全部方法的正则匹配字符串 - * - * @return - */ - protected static String getMethodNameRegexs() { - return Mock.getMockMethods().keySet().stream().map(method -> method.replaceAll("(\\(.*\\))", "")).distinct().collect(Collectors.joining("|", "(", ")")); - } - - - - /* —————————————————— 获取各种参数获取器的方法 —————————————————————— */ - - /* —————————————————— Integer参数获取器的方法 —————————————————————— */ - /** - * 获取随机整数的方法名,有三种参数: - * {@link com.forte.util.utils.MockUtil#integer()}获取随机数字 0-9 - * {@link com.forte.util.utils.MockUtil#integer(Integer)}获取指定长度的随机数,※不可超过int最大上限 - * {@link com.forte.util.utils.MockUtil#integer(Integer, Integer)}获取指定区间[a,b]的随机数,※不可超过int最大上限 - */ - private static final String INTEGER_METHOD_NAME = "@integer"; - - /** - * 获取随机整数方法执行者,由于整数三种参数中方法的执行类型不同,则需要分为三个方法 - * @return - */ - private Invoker getIntegerMethodInvoker(Integer intIntervalMin , Integer intIntervalMax){ - //拼接出方法 - //获取方法字符串 - String methodStr = INTEGER_METHOD_NAME + - "(" + - intIntervalMin + - "," + - intIntervalMax + - ")" - //获取方法字符串 - ; - - //返回方法执行者 - return getOneMethodInvoker(methodStr); - } - /** - * 获取随机整数方法执行者,由于整数三种参数中方法的执行类型不同,则需要分为三个方法 - * @return - */ - private Invoker getIntegerMethodInvoker(Integer intIntervalLength){ - //拼接出方法 - StringBuilder methodBuilder = new StringBuilder(); - methodBuilder.append(INTEGER_METHOD_NAME); - methodBuilder.append("("); - methodBuilder.append(intIntervalLength); - methodBuilder.append(")"); - - //获取方法字符串 - String methodStr = methodBuilder.toString(); - - //返回方法执行者 - return getOneMethodInvoker(methodStr); - } - /** - * 获取随机整数方法执行者,由于整数三种参数中方法的执行类型不同,则需要分为三个方法 - * @return - */ - private Invoker getIntegerMethodInvoker(){ - //拼接出方法 - //获取方法字符串 - String methodStr = INTEGER_METHOD_NAME + "()"; - - //返回方法执行者 - return getOneMethodInvoker(methodStr); - } - - /** - * 获取一个整数类型字段值获取器 - * @param intIntervalMin - * @param intIntervalMax - * @return - */ - protected IntegerFieldValueGetter getIntegerFieldValueGetter(Integer intIntervalMin , Integer intIntervalMax){ - //获取一个整数类型字段值获取器 - //获取随机整数方法执行者 - Invoker integerMethodInvoker = getIntegerMethodInvoker(intIntervalMin, intIntervalMax); - - //创建整数类型字段值获取器 - return new IntegerFieldValueGetter(integerMethodInvoker); - } - - /** - * 获取一个整数类型字段值获取器 - * @param intIntervalLength - * 整数的长度 - * @return - */ - protected IntegerFieldValueGetter getIntegerFieldValueGetter(Integer intIntervalLength){ - //获取一个整数类型字段值获取器 - //获取随机整数方法执行者 - Invoker integerMethodInvoker = getIntegerMethodInvoker(intIntervalLength); - - //创建整数类型字段值获取器 - return new IntegerFieldValueGetter(integerMethodInvoker); - } - - /** - * 获取一个整数类型字段值获取器 - * @return - */ - protected IntegerFieldValueGetter getIntegerFieldValueGetter(){ - //获取一个整数类型字段值获取器 - //获取随机整数方法执行者 - Invoker integerMethodInvoker = this::getIntegerMethodInvoker; - - //创建整数类型字段值获取器 - return new IntegerFieldValueGetter(integerMethodInvoker); - } - - - /* —————————————————— Double参数获取器的方法 —————————————————————— */ - /** - * 获取随机小数的方法名,有4种参数: - * {@link com.forte.util.utils.MockUtil#doubles(Integer, Integer, Integer, Integer)}获取制定区间[a,b]的小数,指定小数位数[endL,endR],double类型 - * {@link com.forte.util.utils.MockUtil#doubles(Integer, Integer, Integer)}获取制定区间[a,b]的小数,指定小数位数[end],double类型 - * {@link com.forte.util.utils.MockUtil#doubles(Integer, Integer)}获取指定区间[a,b]的小数,默认小数位数为0,double类型 - * {@link com.forte.util.utils.MockUtil#doubles(Integer)}获取指定数值为a的小数,默认小数位数为0,double类型 - * - */ - private final String DOUBLE_METHOD_NAME = "@doubles"; - - - - /** - * 获取随机小数的方法执行者 - * @param intIntervalMin - * @param intIntervalMax - * @param doubleIntervalMin - * @param doubleIntervalMax - * @return - */ - private Invoker getDoublesMethodInvoker(Integer intIntervalMin, Integer intIntervalMax, Integer doubleIntervalMin, Integer doubleIntervalMax){ - StringBuilder strForMethod = new StringBuilder(); - strForMethod.append(DOUBLE_METHOD_NAME); - strForMethod.append("("); - strForMethod.append(intIntervalMin); - strForMethod.append(","); - strForMethod.append(intIntervalMax); - strForMethod.append(","); - strForMethod.append(doubleIntervalMin); - strForMethod.append(","); - strForMethod.append(doubleIntervalMax); - strForMethod.append(")"); - - String methodStr = strForMethod.toString(); - - //获取并返回方法执行者 - return getOneMethodInvoker(methodStr); - - } - - /** - * 获取小数字段值获取器 - * @param intInterval - * 整数部分数值 - * @return - */ - protected DoubleFieldValueGetter getDoubleFieldValueGetter(Integer intInterval){ - //获取方法执行者 - String methodName = DOUBLE_METHOD_NAME + "("+ intInterval +")"; - //获取方法执行者 - Invoker oneMethodInvoker = getOneMethodInvoker(methodName); - - //创建并返回double字段值获取器 - return new DoubleFieldValueGetter(oneMethodInvoker); - } - - /** - * 获取小数字段值获取器 - * @param intIntervalMin - * 整数部分区间最小值 - * @param intIntervalMax - * 整数部分区间最大值 - * @return - */ - protected DoubleFieldValueGetter getDoubleFieldValueGetter(Integer intIntervalMin , Integer intIntervalMax){ - return getDoubleFieldValueGetter(intIntervalMin , intIntervalMax , 0 , 0); - } - - /** - * 获取小数字段值获取器 - * @param intIntervalMin - * 整数部分最小数区间 - * @param intIntervalMax - * 整数部分最大数区间 - * @param doubleInterval - * 小数部分位数 - * @return - */ - protected DoubleFieldValueGetter getDoubleFieldValueGetter(Integer intIntervalMin , Integer intIntervalMax , Integer doubleInterval){ - return getDoubleFieldValueGetter(intIntervalMin , intIntervalMax , doubleInterval , doubleInterval); - } - - /** - * 获取小数字段值获取器 - * @param intIntervalMin - * 整数部分最小数区间 - * @param intIntervalMax - * 整数部分最大数区间 - * @param doubleIntervalMin - * 小数部分最小位数区间 - * @param doubleIntervalMax - * 小数部分最大位数区间 - * @return - */ - protected DoubleFieldValueGetter getDoubleFieldValueGetter(Integer intIntervalMin , Integer intIntervalMax , Integer doubleIntervalMin , Integer doubleIntervalMax){ - //有一下4种情况种可能, - //1 - 4个参数都有 - //2 - 整数部分没有右参数 - //3 - 小数部分没有右参数 - //4 - 整数和小数都没有右边参数 - - //先判断两部分的右参数,如果没有则赋值与左参数相同 - intIntervalMax = Optional.ofNullable(intIntervalMax).orElse(intIntervalMin); - doubleIntervalMax = Optional.ofNullable(doubleIntervalMax).orElse(intIntervalMin); - - - //现在只有一种情况:4个参数都有,拼接参数 - //获取方法执行者 - Invoker oneMethodInvoker =getDoublesMethodInvoker(intIntervalMin , intIntervalMax , doubleIntervalMin , doubleIntervalMax); - - //创建并返回double字段值获取器 - return new DoubleFieldValueGetter(oneMethodInvoker); - } - - - /* —————————————————— Array参数获取器的方法 —————————————————————— */ - - - /** - * 获取一个List类型字段值获取器 - * - * @param invokers 方法执行者 - * @param integerInterval 区间参数 - * @param moreStrs 多余字符 - */ - protected FieldValueGetter getArrayFieldValueGetter(Invoker[] invokers, Integer[] integerInterval, String[] moreStrs) { - if (integerInterval == null) { - //创建对象并返回 - return new ArrayFieldValueGetter(invokers, moreStrs); - } else { - //创建对象并返回 - return new ArrayFieldValueGetter(invokers, integerInterval, moreStrs); - } - } - - /** - * 获取一个List类型字段值获取器 - * @param invokers - * 方法执行者 - * @param integerInterval - * 区间参数 - * @return - */ - protected FieldValueGetter getArrayFieldValueGetter(Invoker[] invokers, Integer[] integerInterval) { - if (integerInterval == null) { - //创建对象并返回 - return new ArrayFieldValueGetter(invokers); - } else { - //创建对象并返回 - return new ArrayFieldValueGetter(invokers, integerInterval); - } - } - - - /** - * 获取一个数组类字段值获取器 - * - * @param invokers 方法执行者 - * @param integerInterval 区间参数 - * @param moreStrs 多余字符 - */ - protected FieldValueGetter getArrayFieldValueGetter(List invokers, Integer[] integerInterval, String[] moreStrs) { - Invoker[] invokersArr = invokers.toArray(new Invoker[0]); - if (integerInterval == null) { - //创建对象并返回 - return new ArrayFieldValueGetter(invokersArr, moreStrs); - } else { - //创建对象并返回 - return new ArrayFieldValueGetter(invokersArr, integerInterval, moreStrs); - } - } - - /** - * 获取一个数组类字段值获取器 - * - * @param invokers 方法执行者 - * @param moreStrs 多余字符 - */ - protected FieldValueGetter getArrayFieldValueGetter(Invoker[] invokers, String[] moreStrs) { - //创建对象并返回 - return getArrayFieldValueGetter(invokers, new Integer[]{intervalMin, intervalMax}, moreStrs); - } - - /** - * 获取一个数组类型字段值获取器 - * - * @param invokers 方法执行者 - * @param moreStrs 多余字符 - */ - protected FieldValueGetter getArrayFieldValueGetter(List invokers, String[] moreStrs) { - //创建对象并返回 - return getArrayFieldValueGetter(invokers.toArray(new Invoker[0]), new Integer[]{intervalMin, intervalMax}, moreStrs); - } - - - /** - * 获取一个数组类型字段值获取器 - * - * @param invokers 方法执行者 - */ - protected FieldValueGetter getArrayFieldValueGetter(Invoker[] invokers) { - //创建对象并返回 - return new ArrayFieldValueGetter(invokers, new Integer[]{intervalMin, intervalMax}); - } - - /** - * 获取一个数组类型字段值获取器 - * - * @param invokers 方法执行者 - */ - protected FieldValueGetter getArrayFieldValueGetter(List invokers) { - //创建对象并返回 - return new ArrayFieldValueGetter(invokers.toArray(new Invoker[0]), new Integer[]{intervalMin, intervalMax}); - } - - - - /* —————————————————— List参数获取器的方法 —————————————————————— */ - - - /** - * 获取一个List类型字段值获取器 - * - * @param invokers 方法执行者 - * @param integerInterval 区间参数 - * @param moreStrs 多余字符 - */ - protected FieldValueGetter getListFieldValueGetter(Invoker[] invokers, Integer[] integerInterval, String[] moreStrs) { - if (integerInterval == null) { - //创建对象并返回 - return new ListFieldValueGetter(invokers, moreStrs); - } else { - //创建对象并返回 - return new ListFieldValueGetter(invokers, integerInterval, moreStrs); - } - } - - /** - * 获取一个List类型字段值获取器 - * - * @param invokers 方法执行者 - * @param integerInterval1 区间参数 - * @param integerInterval2 区间参数 - * @param moreStrs 多余字符 - */ - protected FieldValueGetter getListFieldValueGetter(Invoker[] invokers, Integer[] integerInterval1, Integer[] integerInterval2, String[] moreStrs) { - if (integerInterval1 == null && integerInterval2 == null) { - //创建对象并返回 - return new ListFieldValueGetter(invokers, moreStrs); - } else { - //创建对象并返回 - return new ListFieldValueGetter(invokers, integerInterval1, integerInterval2, moreStrs); - } - } - - /** - * 获取一个List类型字段值获取器 - * - * @param invokers 方法执行者 - * @param integerInterval 区间参数 - */ - protected FieldValueGetter getListFieldValueGetter(Invoker[] invokers, Integer[] integerInterval) { - if (integerInterval == null) { - //创建对象并返回 - return new ListFieldValueGetter(invokers); - } else { - //创建对象并返回 - return new ListFieldValueGetter(invokers, integerInterval); - } - } - - /** - * 获取一个List类型字段值获取器 - * - * @param invokers 方法执行者 - * @param integerInterval1 区间参数 - * @param integerInterval2 区间参数 - */ - protected FieldValueGetter getListFieldValueGetter(Invoker[] invokers, Integer[] integerInterval1, Integer[] integerInterval2) { - if (integerInterval1 == null && integerInterval2 == null) { - //创建对象并返回 - return new ListFieldValueGetter(invokers); - } else { - //创建对象并返回 - return new ListFieldValueGetter(invokers, integerInterval1, integerInterval2); - } - } - - /** - * 获取一个List类型字段值获取器 - * - * @param invokers 方法执行者 - * @param integerInterval 区间参数 - * @param moreStrs 多余字符 - */ - protected FieldValueGetter getListFieldValueGetter(List invokers, Integer[] integerInterval, String[] moreStrs) { - Invoker[] invokersArr = invokers.toArray(new Invoker[0]); - if (integerInterval == null) { - //创建对象并返回 - return new ListFieldValueGetter(invokersArr, moreStrs); - } else { - //创建对象并返回 - return new ListFieldValueGetter(invokersArr, integerInterval, moreStrs); - } - } - - /** - * 获取一个List类型字段值获取器 - * - * @param invokers 方法执行者 - * @param integerInterval 区间参数 - */ - protected FieldValueGetter getListFieldValueGetter(List invokers, Integer[] integerInterval) { - Invoker[] invokersArr = invokers.toArray(new Invoker[0]); - if (integerInterval == null) { - //创建对象并返回 - return new ListFieldValueGetter(invokersArr); - } else { - //创建对象并返回 - return new ListFieldValueGetter(invokersArr, integerInterval); - } - } - - /** - * 获取一个List类型字段值获取器 - * - * @param invokers 方法执行者 - * @param moreStrs 多余字符 - */ - protected FieldValueGetter getListFieldValueGetter(Invoker[] invokers, String[] moreStrs) { - //创建对象并返回 - return getListFieldValueGetter(invokers, new Integer[]{intervalMin, intervalMax}, moreStrs); - } - - - /** - * 获取一个List类型字段值获取器 - * - * @param invokers 方法执行者 - * @param moreStrs 多余字符 - */ - protected FieldValueGetter getListFieldValueGetter(List invokers, String[] moreStrs) { - //创建对象并返回 - return getListFieldValueGetter(invokers.toArray(new Invoker[0]), new Integer[]{intervalMin, intervalMax}, moreStrs); - } - - - /** - * 获取一个List类型字段值获取器 - * - * @param invokers 方法执行者 - */ - protected FieldValueGetter getListFieldValueGetter(Invoker[] invokers) { - //创建对象并返回 - return new ListFieldValueGetter(invokers, new Integer[]{intervalMin, intervalMax}); - } - - /** - * 获取一个List类型字段值获取器 - * - * @param invokers 方法执行者 - */ - protected FieldValueGetter getListFieldValueGetter(List invokers) { - //创建对象并返回 - return new ListFieldValueGetter(invokers.toArray(new Invoker[0]), new Integer[]{intervalMin, intervalMax}); - } - - - - - /* —————————————————— Object参数获取器的方法 —————————————————————— */ - - - /** - * 获取一个未知引用类型参数获取器 - * - * @return - */ - protected FieldValueGetter getObjectFieldValueGetter(Invoker... invokers) { - return new ObjectFieldValueGetter(invokers); - } - - /** - * 获取一个未知引用类型参数获取器 - * - * @return - */ - protected FieldValueGetter getObjectFieldValueGetter(List invokers) { - return new ObjectFieldValueGetter(invokers.toArray(new Invoker[0])); - } - - - /* —————————————————— String参数获取器的方法 —————————————————————— */ - - - /** - * 获取一个字符串参数获取器 - * - * @param invokers 方法执行者数组 - * @param methodsSplit 多余字符数组 - * @param intervalArray 区间参数 - * @return - */ - protected FieldValueGetter getStringFieldValueGetter(Invoker[] invokers, String[] methodsSplit, Integer[] intervalArray) { - //获取 StringFieldValueGetter参数获取器,如果有整数位的区间参数,添加参数 - //使用三元运算判断 - //如果为空||长度小于1||长度大于2||索引0为空 - boolean intervalArrayIsRight = !(intervalArray == null || intervalArray.length < 1 || intervalArray.length >= 2 || intervalArray[0] == null); - return intervalArrayIsRight ? - new StringFieldValueGetter(invokers, methodsSplit, intervalArray) - : - new StringFieldValueGetter(invokers, methodsSplit); - } - - - /** - * 获取一个字符串参数获取器 - * - * @param invokers 方法执行者数组 - * @param methodsSplit 多余字符数组 - * @return - */ - protected FieldValueGetter getStringFieldValueGetter(Invoker[] invokers, String[] methodsSplit) { - //获取 StringFieldValueGetter参数获取器,如果有整数位的区间参数,添加参数 - //使用三元运算判断 - return intervalMax == null ? - new StringFieldValueGetter(invokers, methodsSplit) - : - new StringFieldValueGetter(invokers, methodsSplit, new Integer[]{intervalMin, intervalMax}); - } - - /** - * 获取一个字符串参数获取器 - * - * @param invokers 方法执行者集合 - * @param methodsSplit 多余字符数组 - * @return - */ - protected FieldValueGetter getStringFieldValueGetter(List invokers, String[] methodsSplit) { - return getStringFieldValueGetter(invokers.toArray(new Invoker[0]), methodsSplit); - } - - /** - * 获取一个没有多余字符的字符串字段值获取器 - * - * @param invokers 方法执行者数组 - * @return - */ - protected FieldValueGetter getStringFieldValueGetter(Invoker[] invokers) { - return getStringFieldValueGetter(invokers, null); - } - - /** - * 获取一个没有多余字符的字符串字段值获取器 - * - * @param invokers 方法执行者集合 - * @return - */ - protected FieldValueGetter getStringFieldValueGetter(List invokers) { - return getStringFieldValueGetter(invokers, null); - } - - - - - /* ————————————————————— 构造 ————————————————————— */ - - - /** - * 构造 - * - * @param objectClass - * @param fieldName - * @param intervalStr - */ - public BaseFieldParser(Class objectClass, String fieldName, String intervalStr) { - //保存数据 - this.objectClass = objectClass; - this.fieldName = fieldName; - //获取此字段的数据类型 - if(objectClass != null) - this.fieldClass = FieldUtils.fieldClassGetter(objectClass, fieldName); - else - this.fieldClass = Object.class; - //解析区间参数,如果有的话 - if (intervalStr != null) { - //切割,看看有没有小数位的区间 - //期望中,切割后长度最多为2 - String[] split = intervalStr.split("\\."); - //整数位的区间参数 - String integerInterval = split[0].trim(); - if (integerInterval.length() > 0) { - //如果不是空的,切割并记录 - String[] splitIntInterval = integerInterval.split("-"); - this.intervalMin = Integer.parseInt(splitIntInterval[0]); - this.intervalMax = splitIntInterval.length > 1 ? Integer.parseInt(splitIntInterval[1]) : null; - } else { - //否则赋值为空 - this.intervalMin = null; - this.intervalMax = null; - } - - //如果切割后的长度不只一个,说明还有小数位数 - if (split.length > 1) { - String doubleInterval = split[1].trim(); - //如果小数位上有值 - if (doubleInterval.length() > 0) { - //如果不是空的,切割并记录 - String[] splitDouInterval = doubleInterval.split("\\-"); - this.intervalDoubleMin = Integer.parseInt(splitDouInterval[0]); - this.intervalDoubleMax = splitDouInterval.length > 1 ? Integer.parseInt(splitDouInterval[1]) : null; - } else { - //否则赋空值 - this.intervalDoubleMax = null; - this.intervalDoubleMin = null; - } - - } else { - //如果没有,赋值为空 - this.intervalDoubleMax = null; - this.intervalDoubleMin = null; - } - } else { - //如果没有,赋值为null - this.intervalMin = null; - this.intervalMax = null; - this.intervalDoubleMax = null; - this.intervalDoubleMin = null; - - } - } -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/DoubleParser.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/DoubleParser.java deleted file mode 100644 index 7037bf7..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/DoubleParser.java +++ /dev/null @@ -1,203 +0,0 @@ -package io.fluent.mocker.parser; - -import com.forte.util.fieldvaluegetter.FieldValueGetter; -import com.forte.util.invoker.Invoker; -import com.forte.util.utils.MethodUtil; - -import java.util.ArrayList; -import java.util.Optional; - -/** - * double浮点型参数解析器,相对与指令解析,此解析器相对比较简单。 - * 只需要根据区间参数,获取相应的浮点数即可 - * - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -class DoubleParser extends BaseFieldParser { - - /** - * 参数默认值,唯一构造保证其必定有值,默认值为0 - */ - private Double defaultValue; - - - /** - * 当字段既不是集合也不是数组的时候,获取其字段值获取器 - * 字段不是集合也不是数组,且参数为Double,则说明区间参数代表了取值的随机范围 - * @return - */ - @Override - public FieldValueGetter parserForNotListOrArrayFieldValueGetter() { - //判断小数部分的区间参数 - 将参数判断提为单独的方法 - //获取区间参数 - Integer[][] intervalsData = getIntervalsData(); - - //整理结果 - //map 转化为doubleFieldValueGetter - //如果为空则返回默认值 - return Optional.ofNullable(intervalsData).map(i -> (FieldValueGetter) getDoubleFieldValueGetter(i[0][0], i[0][1], i[1][0], i[1][1])).orElse(() -> defaultValue); - } - - /** - * 当字段是集合的时候,获取其字段值获取器 - * 如果字段为集合,参数为Double - * 则区间参数变为List集合的长度区间,将无视小数部分的区间参数 - * list集合的值为默认值 - * @return - */ - @Override - public FieldValueGetter parserForListFieldValueGetter() { - //获取整数区间参数 - Integer[] intIntervalsData = getIntIntervalsData(); - //将区间参数转化为list集合,如果不存在则返回空集合 - //并返回 - return Optional.ofNullable(intIntervalsData).map(i -> { - //获取空值执行者 - Invoker nullMethodInvoker = MethodUtil.createNullMethodInvoker(defaultValue); - //返回结果 - return getListFieldValueGetter(new Invoker[]{nullMethodInvoker}, i); - }).orElse(ArrayList::new); - } - - /** - * 当字段是数组的时候,获取其字段值获取器 - * 如果字段为数组,参数为Double - * 则区间参数变为数组的长度区间,将无视小数部分的区间参数 - * @return - */ - @Override - public FieldValueGetter parserForArrayFieldValueGetter() { - // 将结果整合为数组并返回 - // 方式类似于List集合,仅返回值不同 - //获取整数区间参数 - Integer[] intIntervalsData = getIntIntervalsData(); - //将区间参数转化为数组,如果不存在则返回空集合 - //并返回 - return Optional.ofNullable(intIntervalsData).map(i -> { - //获取空值执行者 - Invoker nullMethodInvoker = MethodUtil.createNullMethodInvoker(defaultValue); - //返回结果 - return getArrayFieldValueGetter(new Invoker[]{nullMethodInvoker}, i); - }).orElse(() -> new Double[0]); - } - - - - /** - * 仅获取整数部分的区间参数 - * @return - */ - private Integer[] getIntIntervalsData(){ - //准备数组 - Integer[] intIntervals = new Integer[2]; - - //初始化参数 - Integer intIntervalMin = intervalMin; - Integer intIntervalMax = intervalMax; - - //判断整数位区间参数 - if (intIntervalMin == null) { - //如果没有整数位左参数,判断是否存在右参数 - if (intIntervalMax == null) { - // 如果右参数也为null,直接返回null - return null; - } else { - // 有右参数,没有左参数,按照仅有左参数处理 - intIntervalMin = intIntervalMax; - } - }else{ - //有左参数,判断是否有右参数 - if (intIntervalMax == null) { - // 如果右参数为null,赋值为左参数 - intIntervalMax = intIntervalMin; - } - // 两参数都有,不变 - } - - //为结果赋值 - intIntervals[0] = intIntervalMin; - intIntervals[1] = intIntervalMax; - - //返回结果 - return intIntervals; - } - - /** - * 仅获取小数部分的区间参数 - * @return - */ - private Integer[] getDoubleIntervalsData(){ - //准备结果 - Integer[] doubleIntervals = new Integer[2]; - - //初始化参数 - Integer doubleIntervalMin = intervalDoubleMin; - Integer doubleIntervalMax = intervalDoubleMax; - - //判断小数区间,判断方法与整数基本一致 - if (doubleIntervalMin == null) { - //如果没有整数位左参数,判断是否存在右参数 - if (doubleIntervalMax == null) { - // 如果右参数也为null,将两值设为0 - doubleIntervalMin = doubleIntervalMax = 0; - } else { - // 有右参数,没有左参数,按照仅有左参数处理 - doubleIntervalMin = doubleIntervalMax; - } - }else{ - //有左参数,判断是否有右参数 - if (doubleIntervalMax == null) { - // 如果右参数为null,赋值为左参数 - doubleIntervalMax = doubleIntervalMin; - } - // 两参数都有,不变 - } - - - //为结果赋值 - doubleIntervals[0] = doubleIntervalMin; - doubleIntervals[1] = doubleIntervalMax; - - //返回结果 - return doubleIntervals; - } - - /** - * 获取转化好的区间参数 - * @return - * 返回值为二维数组, - * 索引0为整数部分的区间数组,[0]为左参数,[1]为右参数 - * 索引1为小数部分的区间参数,[0]为左参数,[1]为右参数 - * 假如返回值为null,则说明没有区间参数 - */ - private Integer[][] getIntervalsData(){ - Integer[] intIntervals = new Integer[2]; - Integer[] doubleIntervals = new Integer[2]; - Integer[][] intervals = new Integer[][]{intIntervals , doubleIntervals}; - - //获取整数部分区间参数,可能为null - Integer[] intIntervalsData = getIntIntervalsData(); - //获取小数部分区间参数,此结果必定不为null - Integer[] doubleIntervalsData = getDoubleIntervalsData(); - - //返回结果 - //如果整数区间不为null,则转化为二维数组并返回,如果不存在则返回null - return Optional.ofNullable(intIntervalsData).map(i -> new Integer[][]{intIntervalsData , doubleIntervalsData}).orElse(null); - } - - - /** - * 构造 - * - * @param objectClass - * @param fieldName - * @param intervalStr - * @param defaultValue 默认值,如果未null则默认为0 - */ - public DoubleParser(Class objectClass, String fieldName, String intervalStr, Double defaultValue) { - super(objectClass, fieldName, intervalStr); - //如果默认值为null,赋值为0 - this.defaultValue = defaultValue == null ? 0 : defaultValue; - } - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/FieldParser.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/FieldParser.java deleted file mode 100644 index ee2c3d4..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/FieldParser.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.fluent.mocker.parser; - -import com.forte.util.fieldvaluegetter.FieldValueGetter; -import com.forte.util.mockbean.MockField; - -/** - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -public interface FieldParser { - - /** - * 若字段不是List集合时的解析方法 - * - * @return 字段值获取器 - */ - FieldValueGetter parserForNotListOrArrayFieldValueGetter(); - - - /** - * 若字段是集合时的解析方法 - * - * @return 字段值获取器 - */ - FieldValueGetter parserForListFieldValueGetter(); - - - /** - * 若字段是数组时的解析方法 - * - * @return 字段值获取器 - */ - FieldValueGetter parserForArrayFieldValueGetter(); - - - /** - * 获取一个假字段对象,为参数解析器准备 - * @return - */ - MockField getMockField(); - - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/InstructionParser.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/InstructionParser.java deleted file mode 100644 index 8b185ce..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/InstructionParser.java +++ /dev/null @@ -1,241 +0,0 @@ -package io.fluent.mocker.parser; - -import com.forte.util.Mock; -import com.forte.util.fieldvaluegetter.FieldValueGetter; -import com.forte.util.invoker.Invoker; -import com.forte.util.mockbean.MockObject; -import com.forte.util.utils.MethodUtil; - -import java.util.List; -import java.util.Map; - -/** - * 指令字段解析器 - * - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -class InstructionParser extends BaseFieldParser { - - /** - * 指令的字符串 - */ - private final String instructionStr; - - - /** - * 当字段是数组的时候,进行解析 - */ - @Override - public FieldValueGetter parserForArrayFieldValueGetter() { - //字段是数组类型时的解析方法 - //字段值获取器 - FieldValueGetter fieldValueGetter; - - // 如果指令参数开头为井号'#',则先判断其为一个已经存在的类型名称 - if(instructionStr.startsWith("#")){ - final MockObject mockObject = Mock.get(instructionStr.substring(1)); - if(mockObject != null){ - fieldValueGetter = getArrayFieldValueGetter(new Invoker[]{mockObject::getOne}); - return fieldValueGetter; - } - } - - //解析指令,查找指令中的@方法 - //先判断是否有匹配的方法 - boolean match = match(instructionStr); - if (match) { - //如果指令中有方法 - //解析出方法名 - String[] methods = getMethods(instructionStr); - //解析方法并获取方法执行者 - List invoker = getMethodInvoker(methods); - //获取多余字符 - String[] methodsSplit = getMethodsSplit(instructionStr); - //获取list类型字段值获取器 - fieldValueGetter = getArrayFieldValueGetter(invoker, methodsSplit); - - } else { - //如果没有@方法,则说明list集合是String集合或者是可以使用eval函数执行的js代码 - //则创建一个空执行者,将参数作为其输出值 - Invoker nullInvoker = MethodUtil.createNullMethodInvoker(instructionStr); - - //创建字段值获取器 - fieldValueGetter = getArrayFieldValueGetter(new Invoker[]{nullInvoker}); - } - - //返回字段值获取器 - return fieldValueGetter; - } - - /** - * 当字段是list集合的时候进行解析 - */ - @Override - public FieldValueGetter parserForListFieldValueGetter() { - //字段是数组类型时的解析方法 - //字段值获取器 - FieldValueGetter fieldValueGetter; - - // 如果指令参数开头为井号'#',则先判断其为一个已经存在的类型名称 - if(instructionStr.startsWith("#")){ - final MockObject mockObject = Mock.get(instructionStr.substring(1)); - if(mockObject != null){ - fieldValueGetter = getListFieldValueGetter(new Invoker[]{mockObject::getOne}); - return fieldValueGetter; - } - } - - //解析指令,查找指令中的@方法 - //先判断是否有匹配的方法 - boolean match = match(instructionStr); - if (match) { - //如果指令中有方法 - //解析出方法名 - String[] methods = getMethods(instructionStr); - //解析方法并获取方法执行者 - List invoker = getMethodInvoker(methods); - //获取多余字符 - String[] methodsSplit = getMethodsSplit(instructionStr); - //获取list类型字段值获取器 - fieldValueGetter = getListFieldValueGetter(invoker, methodsSplit); - - } else { - //如果没有@方法,则说明list集合是String集合或者是可以使用eval函数执行的js代码 - //则创建一个空执行者,将参数作为其输出值 - Invoker nullInvoker = MethodUtil.createNullMethodInvoker(instructionStr); - - //创建字段值获取器 - fieldValueGetter = getListFieldValueGetter(new Invoker[]{nullInvoker}); - } - - - //返回字符值获取器 - return fieldValueGetter; - } - - - /** - * 当字段既不是数组又不是集合的时候,进行解析 - * - * @return 字段值获取器 - */ - @Override - public FieldValueGetter parserForNotListOrArrayFieldValueGetter() { - /* - 假如字段类型为Object类型且存在区间参数,则认为这是一个需要转化为集合的类型,即认为字段类型为List类型,直接使用List字段值生成器 - 区间参数只要存在左参数即为存在 - */ - boolean isObjectToList = this.fieldClass.equals(Object.class) && (intervalMin != null); - if(isObjectToList){ - return this.parserForListFieldValueGetter(); - } - - - //字段值获取器 - FieldValueGetter fieldValueGetter; - - // 如果指令参数开头为井号'#',则先判断其为一个已经存在的类型名称 - if(instructionStr.startsWith("#")){ - final MockObject mockObject = Mock.get(instructionStr.substring(1)); - if(mockObject != null){ - fieldValueGetter = mockObject::getOne; - return fieldValueGetter; - } - } - - //解析指令,查找指令中的@方法 - //先判断是否有匹配的方法 - boolean match = match(instructionStr); - if (match) { - //如果存在指令方法 - //解析出方法名 - String[] methods = getMethods(instructionStr); - //如果有方法,解析方法,解析参数-由于做过判断,所以此处必然有方法 - - //解析方法并获取方法执行者 - List invoker = getMethodInvoker(methods); - - //获取多余字符 - String[] methodsSplit = getMethodsSplit(instructionStr); - //如果参数多余字符不为0,则参数类型必定为String且methodsSplit[]的长度必定为methods[]的长度+1或与methods[]的长度相等 - //则必定为字符串字段 - //有指令方法的时候,如果有区间参数,对字符串的最终输出进行重复 - if (methodsSplit.length > 0) { - //获取 StringFieldValueGetter字段值获取器,如果有整数位的区间参数,添加参数 - //使用三元运算判断 - fieldValueGetter = getStringFieldValueGetter(invoker, methodsSplit); - } else { - //如果没有多余字符,则字段可能不是字符串类型, - //判断字段的数据类型 - if (fieldClass.equals(String.class)) { - //如果是String类型的,使用StringFieldValueGetter字段值获取器 - fieldValueGetter = getStringFieldValueGetter(invoker); - } else { - //如果字段类型不是String,则不能用StringFieldValueGetter字段值获取器了 - //使用ObjectFieldValueGetter,不指定参数获取值 - fieldValueGetter = getObjectFieldValueGetter(invoker); - } - } - } else { - //如果没有能够匹配的@方法,则说明指令部分就是普通的字符串,创建一个方法执行者为空值的未知类型字段值获取器: ObjectFieldValueGetter - Integer[] intervalData = getIntervalData(); - //判断区间参数是否存在 - if(intervalData == null){ - //因为是没有@方法的普通字符串,没有多余字符,使用Object类型的字段值获取器即可 - fieldValueGetter = getObjectFieldValueGetter(MethodUtil.createNullMethodInvoker(instructionStr)); - }else{ - //有区间参数,获取一个对字符串重复输出的Invoker - fieldValueGetter = getStringFieldValueGetter(new Invoker[]{MethodUtil.createNullMethodInvoker(instructionStr)}); - } - - - } - //返回结果 - return fieldValueGetter; - } - - - /** - * 获取区间参数区间,如果没有区间参数则返回null - * @return - */ - private Integer[] getIntervalData(){ - //获取参数 - Integer min = intervalMin; - Integer max = intervalMax; - - //判断区间参数 - if(min == null){ - //如果没左参数 - if(max == null){ - //如果右参数也没有,直接返回一个[1,1]的区间 - return null; - }else{ - //如果有右参数,参数同化 - min = max; - } - }else{ - //有左参数,判断右参数 - if(max == null){ - //没有右参数,同化 - max = min; - } - //否则都有,不变 - } - //返回结果 - return new Integer[]{min ,max}; - } - - /** - * 构造 - * - * @param objectClass 类的class对象 - * @param fieldName 字段名称 - * @param intervalStr 区间参数字符串 - * @param instructionStr 指令字符串 - */ - public InstructionParser(Class objectClass, String fieldName, String intervalStr, String instructionStr) { - super(objectClass, fieldName, intervalStr); - this.instructionStr = instructionStr; - } -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/IntegerParser.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/IntegerParser.java deleted file mode 100644 index 92bf6be..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/IntegerParser.java +++ /dev/null @@ -1,128 +0,0 @@ -package io.fluent.mocker.parser; - -import com.forte.util.fieldvaluegetter.FieldValueGetter; -import com.forte.util.invoker.Invoker; -import com.forte.util.utils.MethodUtil; - -import java.util.ArrayList; -import java.util.Optional; - -/** - * Integer整数类型字段解析器 - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -class IntegerParser extends BaseFieldParser { - - /** 默认值 */ - private Integer defaultValue; - - - /** - * 当字段类型既不是list集合也不是数组的时候,获取字段值获取器 - * @return - */ - @Override - public FieldValueGetter parserForNotListOrArrayFieldValueGetter() { - //既不是list也不是数组,则结果为一个整数 - //获取区间参数并获取随机整数的方法执行者 - //判断区间参数 - if(intervalMin == null){ - //如果没有左参数,判断是否有右参数 - if(intervalMax == null){ - //如果右参数也为0,则直接返回默认值字段值获取器 -> 使用Lambda表达式 - return () -> defaultValue; - }else{ - //如果有右参数,将有参数视为唯一参数,获取字段值获取器 - return getIntegerFieldValueGetter(intervalMax); - } - }else{ - //如果有左参数,判断有没有右参数 - if(intervalMax == null){ - //如果没有右参数,则将左参数视为唯一参数,获取字段值获取器 - return getIntegerFieldValueGetter(intervalMin); - }else{ - //如果两参数都有,获取字段值获取器 - return getIntegerFieldValueGetter(intervalMin, intervalMax); - } - } - } - - - /** - * 当字段值是List集合时,获取字段值获取器 - * @return - */ - @Override - public FieldValueGetter parserForListFieldValueGetter() { - //字段值是List集合形式,则区间参数为list集合的长度,输出区间内数量的默认值 - //获取一个默认值方法执行者 - Invoker nullMethodInvoker = MethodUtil.createNullMethodInvoker(defaultValue); - //获取区间参数数组 - Integer[] interValData = getInterValData(); - //如果区间参数不为null,获取List字段值获取器,否则获取一个空的集合字段值获取器 - return Optional.ofNullable(interValData).map(i -> getListFieldValueGetter(new Invoker[]{nullMethodInvoker}, i)).orElse(ArrayList::new); - } - - - /** - * 当字段值是数组时,获取字段值获取器 - * @return - */ - @Override - public FieldValueGetter parserForArrayFieldValueGetter() { - //字段值是数组形式,则区间参数为数组的长度,输出区间内数量的默认值 - //获取一个默认值方法执行者 - Invoker nullMethodInvoker = MethodUtil.createNullMethodInvoker(defaultValue); - //获取区间参数数组 - Integer[] interValData = getInterValData(); - //如果区间参数不为null,获取数组字段值获取器,否则获取一个空的数组字段值获取器 - return Optional.ofNullable(interValData).map(i -> getArrayFieldValueGetter(new Invoker[]{nullMethodInvoker}, i)).orElse(() -> new Integer[0]); - } - - - /** - * 获取区间参数数组,用于获取List或数组类型的字段值获取器 - * 长度为2,分别代表最小值,最大值 - * @return - */ - private Integer[] getInterValData(){ - Integer min = intervalMin; - Integer max = intervalMax; - //判断区间参数 - if(min == null){ - //如果没有左参数,判断是否有右参数 - if(max == null){ - //如果右参数也为0,则直接返回null - return null; - }else{ - //如果有右参数,区间参数同化 - min = max; - } - }else{ - //如果有左参数,判断有没有右参数 - if(max == null){ - //如果没有右参数,区间参数同化 - max = min; - } - //如果两参数都有,参数不变 - } - - //返回区间参数数组 - return new Integer[]{min, max}; - } - - - /** - * 构造 - * - * @param objectClass - * @param fieldName - * @param intervalStr - */ - public IntegerParser(Class objectClass, String fieldName, String intervalStr, Integer defaultValue) { - super(objectClass, fieldName, intervalStr); - //默认值赋值 - this.defaultValue = defaultValue; - - } -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/ListParser.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/ListParser.java deleted file mode 100644 index 2600965..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/ListParser.java +++ /dev/null @@ -1,128 +0,0 @@ -package io.fluent.mocker.parser; - -import com.forte.util.fieldvaluegetter.FieldValueGetter; -import com.forte.util.invoker.Invoker; -import com.forte.util.utils.MethodUtil; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -/** - * List类型字段解析器 - * 解析方式与过程大致与{@link ArraysParser}相同 - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -class ListParser extends BaseFieldParser { - - - /** 参数传入的数组 */ - private final List defaultList; - - /** - * 字段类型既不是list集合也不是数组的时候 - * 说明从默认集合中随机获取一个并返回 - * @return - */ - @Override - public FieldValueGetter parserForNotListOrArrayFieldValueGetter() { - //创建一个集合元素获取执行者 - Invoker invoker = MethodUtil.createListElementInvoker(defaultList); - return getObjectFieldValueGetter(invoker); - } - - /** - * 字段类型是list集合的时候 - * @return - */ - @Override - public FieldValueGetter parserForListFieldValueGetter() { - //转化并返回结果 - return getListFieldValueGetter(); - } - - /** - * 字段类型是数组的时候 - * @return - */ - @Override - public FieldValueGetter parserForArrayFieldValueGetter() { - //转化并返回结果 - return getArrayFieldValueGetter(); - } - - /** - * 获取数组字段值获取器 - * @return - */ - private FieldValueGetter getArrayFieldValueGetter(){ - //获取随机元素值执行者 - Invoker invoker = MethodUtil.createListElementInvoker(defaultList); - //因为区间不可能为null,直接转化并返回 - return Optional.of(getIntervalData()).map(i -> { - //如果有区间参数,根据区间参数获取字段值获取器 - return getArrayFieldValueGetter(new Invoker[]{invoker}, i); - }).get(); - } - - /** - * 获取集合字段值获取器 - * @return - */ - private FieldValueGetter getListFieldValueGetter(){ - //获取随机元素值执行者 - Invoker invoker = MethodUtil.createListElementInvoker(defaultList); - //因为区间不可能为null,直接转化并返回 - return Optional.of(getIntervalData()).map(i -> { - //如果有区间参数,根据区间参数获取字段值获取器 - return getListFieldValueGetter(new Invoker[]{invoker}, i); - }).get(); - } - - - - /** - * 获取区间参数区间,如果没有区间参数则返回区间[1,1] - * @return - */ - private Integer[] getIntervalData(){ - //获取参数 - Integer min = intervalMin; - Integer max = intervalMax; - - //判断区间参数 - if(min == null){ - //如果没左参数 - if(max == null){ - //如果右参数也没有,直接返回一个[1,1]的区间 - return new Integer[]{1,1}; - }else{ - //如果有右参数,参数同化 - min = max; - } - }else{ - //有左参数,判断右参数 - if(max == null){ - //没有右参数,同化 - max = min; - } - //否则都有,不变 - } - //返回结果 - return new Integer[]{min ,max}; - } - - - /** - * 构造 - * @param objectClass - * @param fieldName - * @param intervalStr - */ - public ListParser(Class objectClass, String fieldName, String intervalStr, List defaultList) { - super(objectClass, fieldName, intervalStr); - //参数集合,复制一份而并非使用原来的 ->浅拷贝 - this.defaultList = new ArrayList<>(defaultList); - } - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/MockObjectParser.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/MockObjectParser.java deleted file mode 100644 index 005a6a0..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/MockObjectParser.java +++ /dev/null @@ -1,154 +0,0 @@ -package io.fluent.mocker.parser; - -import com.forte.util.fieldvaluegetter.FieldValueGetter; -import com.forte.util.invoker.Invoker; -import com.forte.util.mockbean.MockObject; - -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Supplier; - -/** - * Mock数据类型字段解析器 - * - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -class MockObjectParser extends BaseFieldParser { - - - /** - * 参数中的默认值 - */ - private Supplier> defaultValueSupplier; - - private AtomicReference> fieldValueGetter = new AtomicReference<>(null); - - /** - * 当字段类型既不是集合也不是数组的时候 - */ - @Override - public FieldValueGetter parserForNotListOrArrayFieldValueGetter() { - // 如果字段类型为Object且存在左区间参数,则认为这是一个List类型 - boolean isList = this.fieldClass.equals(Object.class) && (intervalMin != null); - - if (isList) { - return parserForListFieldValueGetter(); - } - //直接获取一个默认值参数获取器 - return () -> getObjectValue().get(); - } - - /** - * 如果字段类型是集合类型 - * - * @return - */ - @Override - public FieldValueGetter parserForListFieldValueGetter() { - //使用集合字段类型获取器 - return getListFieldValueGetter(new Invoker[]{() -> getObjectValue().get()}, getIntervalData(), getIntervalDoubleData()); - } - - /** - * 如果字段类型是数组类型 - * - * @return - */ - @Override - public FieldValueGetter parserForArrayFieldValueGetter() { - //使用集合字段类型获取器 - return getArrayFieldValueGetter(new Invoker[]{() -> getObjectValue().get()}, getIntervalData()); - } - - /** - * 得到获取objectValue的函数。 - * 初始化后,会决定最终是通过Object获取还是MockObject获取。 - */ - private Supplier getObjectValue(){ - return fieldValueGetter.updateAndGet(old -> { - if (old != null) { - return old; - } - final MockObject mockObject = defaultValueSupplier.get(); - if (mockObject == null) { - return () -> defaultValueSupplier; - } else { - return mockObject::getOne; - } - }); - } - - /** - * 获取区间参数区间,如果没有区间参数则返回区间[1,1] - */ - private Integer[] getIntervalData() { - //获取参数 - Integer min = intervalMin; - Integer max = intervalMax; - - //判断区间参数 - if (min == null) { - //如果没左参数 - if (max == null) { - //如果右参数也没有,直接返回一个[1,1]的区间 - return new Integer[]{1, 1}; - } else { - //如果有右参数,参数同化 - min = max; - } - } else { - //有左参数,判断右参数 - if (max == null) { - //没有右参数,同化 - max = min; - } - //否则都有,不变 - } - //返回结果 - return new Integer[]{min, max}; - } - - /** - * 获取小数区间参数区间,如果没有区间参数则返回区间[1,1] - */ - private Integer[] getIntervalDoubleData() { - //获取参数 - Integer min = intervalDoubleMin; - Integer max = intervalDoubleMax; - - //判断区间参数 - if (min == null) { - //如果没左参数 - if (max == null) { - //如果右参数也没有,直接返回一个[1,1]的区间 - return new Integer[]{1, 1}; - } else { - //如果有右参数,参数同化 - min = max; - } - } else { - //有左参数,判断右参数 - if (max == null) { - //没有右参数,同化 - max = min; - } - //否则都有,不变 - } - //返回结果 - return new Integer[]{min, max}; - } - - - /** - * 构造 - * - * @param objectClass 最终的mock对象类型 - * @param fieldName 字段名称 - * @param intervalStr 区间参数列表 - */ - public MockObjectParser(Class objectClass, String fieldName, String intervalStr, Supplier> mockObjectSupplier) { - super(objectClass, fieldName, intervalStr); - //赋值 - this.defaultValueSupplier = mockObjectSupplier; - } - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/ObjectParser.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/ObjectParser.java deleted file mode 100644 index 35db584..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/ObjectParser.java +++ /dev/null @@ -1,99 +0,0 @@ -package io.fluent.mocker.parser; - -import com.forte.util.fieldvaluegetter.FieldValueGetter; -import com.forte.util.invoker.Invoker; - -/** - * 引用数据类型字段解析器 - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -class ObjectParser extends BaseFieldParser { - - - /** 参数中的默认值 */ - private Object defaultValue; - - /** - * 当字段类型既不是集合也不是数组的时候 - * @return - */ - @Override - public FieldValueGetter parserForNotListOrArrayFieldValueGetter() { - // 如果字段类型为Object且存在左区间参数,则认为这是一个List类型 - boolean isList = this.fieldClass.equals(Object.class) && (intervalMin != null); - - if(isList){ - return parserForListFieldValueGetter(); - } - //直接获取一个默认值参数获取器 - return () -> defaultValue; - } - - /** - * 如果字段类型是集合类型 - * @return - */ - @Override - public FieldValueGetter parserForListFieldValueGetter() { - //使用集合字段类型获取器 - return getListFieldValueGetter(new Invoker[]{() -> defaultValue} , getIntervalData()); - } - - /** - * 如果字段类型是数组类型 - * @return - */ - @Override - public FieldValueGetter parserForArrayFieldValueGetter() { - //使用集合字段类型获取器 - return getArrayFieldValueGetter(new Invoker[]{() -> defaultValue} , getIntervalData()); - } - - - /** - * 获取区间参数区间,如果没有区间参数则返回区间[1,1] - * @return - */ - private Integer[] getIntervalData(){ - //获取参数 - Integer min = intervalMin; - Integer max = intervalMax; - - //判断区间参数 - if(min == null){ - //如果没左参数 - if(max == null){ - //如果右参数也没有,直接返回一个[1,1]的区间 - return new Integer[]{1,1}; - }else{ - //如果有右参数,参数同化 - min = max; - } - }else{ - //有左参数,判断右参数 - if(max == null){ - //没有右参数,同化 - max = min; - } - //否则都有,不变 - } - //返回结果 - return new Integer[]{min ,max}; - } - - - /** - * 构造 - * - * @param objectClass - * @param fieldName - * @param intervalStr - */ - public ObjectParser(Class objectClass, String fieldName, String intervalStr, Object defaultValue) { - super(objectClass, fieldName, intervalStr); - //赋值 - this.defaultValue = defaultValue; - - } - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/ParameterParser.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/ParameterParser.java deleted file mode 100644 index 9ac0a2e..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/parser/ParameterParser.java +++ /dev/null @@ -1,633 +0,0 @@ -package io.fluent.mocker.parser; - -import com.forte.util.Mock; -import com.forte.util.factory.MockBeanFactory; -import com.forte.util.fieldvaluegetter.ArrayFieldValueGetter; -import com.forte.util.fieldvaluegetter.FieldValueGetter; -import com.forte.util.fieldvaluegetter.ListFieldValueGetter; -import com.forte.util.invoker.Invoker; -import com.forte.util.mockbean.ConstMockField; -import com.forte.util.mockbean.MockBean; -import com.forte.util.mockbean.MockField; -import com.forte.util.mockbean.MockMapBean; -import com.forte.util.utils.FieldUtils; - -import java.util.*; - -/** - * 参数解析器,用于解析用户填入的参数语法 - * 解析包({@link com.forte.util.parser})下唯一公共接口,为{@link Mock}解析用户参数 - * - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -public class ParameterParser { - -// /** -// * MockUtil的方法集 -// */ -// @Deprecated -// private static final Map MOCK_METHOD = Mock._getMockMethod(); - - /* ———— 目前预期类型 ———— - * String / Double / Integer / Map / Object / array&list - */ - - /** - * TODO 注册各种解析器,不再使用switch分配解析器 - */ - // private static final Map, TypeParse> TYPE_PARSE_MAP = new HashMap<>(4); - - /* 内部使用的各类型的常量,用于switch语句,为参数分配解析器 */ - - private static final int TYPE_STRING = 0; - private static final int TYPE_DOUBLE = 1; - private static final int TYPE_INTEGER = 2; - private static final int TYPE_MAP = 3; - private static final int TYPE_OBJECT = 4; - private static final int TYPE_LIST = 5; - private static final int TYPE_ARRAY = 6; - - private static final int TYPE_CLASS = 7; - - /** 常量类型区间。 */ - private static final String CONST_INTERVAL = "const"; - - - /** - * 对参数进行解析-普通类型 - * - * @param objectClass 需要进行假数据封装的类对象 - * @param paramMap 参数集合 - */ - public static MockBean parser(Class objectClass, Map paramMap) { - //使用线程安全list集合 - List fields = new ArrayList<>(); - - Map copyParamsMap = new HashMap<>(paramMap); - - //单程遍历并解析 - copyParamsMap.forEach((key, value) -> { - //解析 - //切割名称,检测是否有区间函数 - String[] split = key.split("\\|"); - //字段名 - String fieldName = split[0]; - //区间参数字符串 - String intervalStr = split.length > 1 ? split[1] : null; - //如果对象不是Map类型且对象中不存在此字段,不进行解析 - if (FieldUtils.isFieldExist(objectClass, fieldName)) { - parser(objectClass, fieldName, intervalStr, value, fields); - } - }); - - - //解析结束,封装MockObject对象 - return getMockBean(objectClass, fields); - } - - /** - * 对参数进行解析-map类型 - * - * @param paramMap 参数集合 - */ - public static MockMapBean parser(Map paramMap) { - List fields = new ArrayList<>(); - - //遍历并解析-(多线程同步) - //如果是.entrySet().parallelStream().forEach的话,似乎会出现一个迷之bug - //如果结果没有任何输出语句打印控制台,会报NullPointer的错 - //已解决,需要使fields这个集合成为线程安全的集合 - /* - 2019/10/18 - 不是干什么都是多线程是好的的,所以遍历不在使用多线程遍历了~ - */ - Set> entries = paramMap.entrySet(); - for (Map.Entry entry : entries) { - String key = entry.getKey(); - Object value = entry.getValue(); - //解析 - //切割名称,检测是否有区间函数 - String[] split = key.split("\\|"); - //字段名 - String fieldName = split[0]; - //区间参数字符串 - String intervalStr = split.length > 1 ? split[1] : null; - //进行解析 - parser(null, fieldName, intervalStr, value, fields); - } - - //解析结束,封装MockObject对象 - return getMockMapBean(fields); - } - - - /** - * 解析 - * - * @param objectClass 封装类型 - * @param fieldName 字段名称 - * @param intervalStr 区间字符串。可能是 const 或者数值区间。 - * @param value 参数 - * @param fields 保存字段用的list - */ - private static void parser(Class objectClass, String fieldName, String intervalStr, Object value, List fields) { - /* - 判断参数类型 - 预期类型: - String / Double / Integer / Map> / object / array 。。。。。。 - */ - //准备字段解析器 - //准备假字段对象 - MockField mockField = null; - - if(intervalStr != null && intervalStr.equalsIgnoreCase(CONST_INTERVAL)) { - // 区间参数为 常量类型,直接使用ConstMockField - mockField = new ConstMockField<>(objectClass, fieldName, value, value.getClass()); - - } else { - int typeNum = typeReferee(value); - //根据字段参数分配解析器 - switch (typeNum) { - case TYPE_STRING: - //是字符串,使用指令解析器 - //获取假字段封装类 - mockField = stringTypeParse(objectClass, fieldName, intervalStr, value); - break; - case TYPE_DOUBLE: - //是Double的浮点型,使用double浮点解析器 - //获取假字段封装类 - mockField = doubleTypeParse(objectClass, fieldName, intervalStr, value); - break; - case TYPE_INTEGER: - //整数解析并获取假字段封装类 - mockField = integerTypeParse(objectClass, fieldName, intervalStr, value); - break; - case TYPE_OBJECT: - //使用解析器,如果字段类型是集合或数组要重复输出 - mockField = objectTypeParse(objectClass, fieldName, intervalStr, value); - break; - case TYPE_MAP: - //如果是一个Map集合,说明这个字段映射着另一个假对象 - //这个Map集合对应的映射类型应该必然是此字段的类型 - //获取假字段对象 - mockField = mapTypeParse(objectClass, fieldName, intervalStr, value); - break; - case TYPE_ARRAY: - //如果value是数组类型,使用数组类型解析器进行解析 - mockField = arrayTypeParse(objectClass, fieldName, intervalStr, value); - break; - case TYPE_LIST: - //如果value是list集合类型,使用集合类型解析器解析 - mockField = listTypeParse(objectClass, fieldName, intervalStr, value); - break; - - case TYPE_CLASS: - // 如果value是class类型的 - mockField = classTypeParse(objectClass, fieldName, intervalStr, value); - break; - default: - System.out.println("无法解析映射类[ " + objectClass + " ]中的字段:" + fieldName); - break; - } - } - - - //添加假字段对象 - fields.add(mockField); - - } - - - - /* —————————————————————— 各个情况的解析方法 —————————————————— */ - - /** - * 字符串类型参数解析 - * - * @param objectClass - * @param fieldName - * @param intervalStr - * @param value - * @return - */ - private static MockField stringTypeParse(Class objectClass, String fieldName, String intervalStr, Object value) { - //是字符串,使用指令解析器 - FieldParser fieldParser = new InstructionParser(objectClass, fieldName, intervalStr, (String) value); - //获取假字段封装类 - return fieldParser.getMockField(); - } - - /** - * double浮点类型解析 - * - * @param objectClass - * @param fieldName - * @param intervalStr - * @param value - * @return - */ - private static MockField doubleTypeParse(Class objectClass, String fieldName, String intervalStr, Object value) { - //是Double的浮点型,使用double浮点解析器 - FieldParser fieldParser = new DoubleParser(objectClass, fieldName, intervalStr, (Double) value); - //获取假字段封装类 - return fieldParser.getMockField(); - } - - /** - * 整数类型解析 - * - * @param objectClass - * @param fieldName - * @param intervalStr - * @param value - * @return - */ - private static MockField integerTypeParse(Class objectClass, String fieldName, String intervalStr, Object value) { - //准备字段解析器 - FieldParser fieldParser; - //如果是整数参数,判断区间参数是否有小数区间 - //如果有区间参数,进行判断 - if (intervalStr != null) { - String[] intervalSplit = intervalStr.split("\\."); - if (intervalSplit.length > 1) { - //如果切割'.'之后长度大于1,则说明有小数位数,使用浮点数解析器 - fieldParser = new DoubleParser(objectClass, fieldName, intervalStr, ((Integer) value) * 1.0); - } else { - //如果长度不大于1,则说明没有小数位数,使用整形解析器 - fieldParser = new IntegerParser(objectClass, fieldName, intervalStr, (Integer) value); - } - } else { - //如果没有区间参数,直接使用整数解析器(此处的intervalStr必定为null) - fieldParser = new IntegerParser(objectClass, fieldName, null, (Integer) value); - } - - //获取假字段封装类 - return fieldParser.getMockField(); - } - - - /** - * 未知的引用数据类型解析 - * - * @param objectClass - * @param fieldName - * @param intervalStr - * @param value - * @return - */ - private static MockField objectTypeParse(Class objectClass, String fieldName, String intervalStr, Object value) { -// ObjectParser objectParser = new ObjectParser(objectClass, fieldName, intervalStr, value); - //返回假字段对象 - return new ObjectParser(objectClass, fieldName, intervalStr, value).getMockField(); - } - - - /** - * Map集合类型解析 - * - * @param objectClass - * @param fieldName - * @param intervalStr - * @param value - * @return - */ - private static MockField mapTypeParse(Class objectClass, String fieldName, String intervalStr, Object value) { - - - //解析区间字符串 - 只关心整数部分字符串 - //切割取整数位 - Integer intervalMin, intervalMax; - // 区间数组,左区间与右区间 - Integer[] integerInterval = new Integer[2]; - if (intervalStr != null) { - String integerIntervalStr = intervalStr.split("\\.")[0].trim(); - //如果不是空的,切割并记录 - String[] splitIntInterval = integerIntervalStr.split("-"); - intervalMin = Integer.parseInt(splitIntInterval[0]); - intervalMax = splitIntInterval.length > 1 ? Integer.parseInt(splitIntInterval[1]) : null; - integerInterval[0] = intervalMin; - integerInterval[1] = intervalMax == null ? intervalMin : intervalMax; - } else { -// intervalMin = intervalMax = null; - integerInterval = null; - } - - //如果是一个Map集合,说明这个字段映射着另一个假对象 - //也有可能只是一个普通的Map而不是映射关系 - //需要判断字段的类型,如果字段类型也是Map,则不进行映射解析而是转化为ObjectField - //这个Map集合对应的映射类型应当必然是此字段的类型 - //获取此字段的class类型 - Class fieldClass; - if (objectClass != null) { - fieldClass = FieldUtils.fieldClassGetter(objectClass, fieldName); - } else { - fieldClass = Object.class; - } - - - //判断类型 - if (FieldUtils.isChild(fieldClass, Map.class)) { - // 直接返回此对象作为假字段对象,不做处理 - return getDefaultObjectMockField(objectClass, fieldName, value, integerInterval, fieldClass); - } else if (FieldUtils.isChild(fieldClass, List.class) && FieldUtils.getListFieldGeneric(objectClass, fieldName).equals(Map.class)) { - //如果字段类型是List集合而且集合的泛型是Map类型,使用Object类型解析器 - ObjectParser objectParser = new ObjectParser(objectClass, fieldName, intervalStr, value); - return objectParser.getMockField(); - } else { - //将参数转化为Map类型 - Map fieldMap = (Map) value; - //如果字段不是Map类型 - //判断字段是否为list集合类型或数组类型 - if (FieldUtils.isChild(fieldClass, List.class)) { - //是list集合类型,获取集合的泛型类型 - Class fieldListGenericClass = FieldUtils.getListFieldGeneric(objectClass, fieldName); - //获取一个假对象 - //同时保存此对象的解析 - MockBean parser = Mock.setResult(fieldListGenericClass, fieldMap, true); - - FieldValueGetter fieldValueGetter = objectToListFieldValueGetter(parser, intervalStr); - return new MockField<>(objectClass, fieldName, fieldValueGetter, fieldClass); - } else if (fieldClass.isArray()) { - //是数组类型,获取数组的类型信息 - Class fieldArrayGeneric = FieldUtils.getArrayGeneric(fieldClass); - //获取一个假对象 -// MockBean parser = parser(fieldArrayGeneric, fieldMap); - //同时保存此对象的解析 - MockBean parser = Mock.setResult(fieldArrayGeneric, fieldMap, true); - - FieldValueGetter fieldValueGetter = objectToArrayFieldValueGetter(parser, intervalStr); - return new MockField<>(objectClass, fieldName, fieldValueGetter, fieldClass); - - } else { - // 如果字段类型为Object类型且存在区间参数,视为List类型处理 - if (fieldClass.equals(Object.class) && intervalStr != null) { - // 解析这个对象, 并作为Map对象 - MockMapBean mockBean = Mock.setResult("", fieldMap, true); - - FieldValueGetter fieldValueGetter = objectToListFieldValueGetter(mockBean, intervalStr); - return new MockField<>(objectClass, fieldName, fieldValueGetter, fieldClass); - } - - //得到一个假对象数据,封装为一个MockField -// MockBean parser = parser(fieldClass, fieldMap); - //同时保存此对象的解析 - if (objectClass == null) { - //如果为null,说明此为map类型对象的解析,则此处同样使用map类型的解析, result的名称使用"" - MockMapBean parser = Mock.setResult("", fieldMap, true); - return objectToField(null, fieldName, parser); - } else { - MockBean parser = Mock.setResult(fieldClass, fieldMap, true); - return objectToField(objectClass, fieldName, parser); - } - } - } - } - - - /** - * 数组类型参数解析 - * - * @param objectClass - * @param fieldName - * @param intervalStr - * @param value - * @return - */ - private static MockField arrayTypeParse(Class objectClass, String fieldName, String intervalStr, Object value) { - //准备字段解析器 - FieldParser fieldParser; - //当参数为一个数组的时候,使用数组解析器 - fieldParser = new ArraysParser(objectClass, fieldName, intervalStr, (Object[]) value); - - //获取假字段封装类 - return fieldParser.getMockField(); - } - - /** - * 集合类型参数解析 - * - * @param objectClass - * @param fieldName - * @param intervalStr - * @param value - * @return - */ - private static MockField listTypeParse(Class objectClass, String fieldName, String intervalStr, Object value) { - //准备字段解析器 - FieldParser fieldParser; - //如果参数是list集合类型的,使用list参数解析器 - fieldParser = new ListParser(objectClass, fieldName, intervalStr, (List) value); - - //获取假字段封装类 - return fieldParser.getMockField(); - } - - /** - * 集合类型参数解析 - * - * @param objectClass - * @param fieldName - * @param intervalStr - * @param value - * @return - */ - private static MockField classTypeParse(Class objectClass, String fieldName, String intervalStr, Object value) { - //准备字段解析器 - FieldParser fieldParser; - //如果参数是list集合类型的,使用list参数解析器 - fieldParser = new MockObjectParser(objectClass, fieldName, intervalStr, () -> Mock.get((Class) value)); - //获取假字段封装类 - return fieldParser.getMockField(); - } - - - /** - * 获取一个默认值假字段 - * - * @param fieldName 字段名 - * @param value 默认值 - * @param integerInterval 区间数组,如果存在的话 - * 如果存在区间函数,则使用ListFieldValueGetter进行构建 - * @return - */ - private static MockField getDefaultObjectMockField(Class objectClass, String fieldName, Object value, Integer[] integerInterval, Class fieldClass) { - if (integerInterval == null) { - return new MockField<>(objectClass, fieldName, () -> value, fieldClass); - } else { - return new MockField<>(objectClass, fieldName, new ListFieldValueGetter( - new Invoker[]{() -> value}, - integerInterval - ), fieldClass); - } - } - - /** - * 将一个假类对象封装为一个假字段对象 - * - * @param object - * @return - */ - private static MockField objectToField(Class objectClass, String fieldName, MockBean object) { - //使用lambda表达式,创建一个MOckField对象并返回 - return new MockField<>(objectClass, fieldName, object::getObject, object.getObjectClass()); - } - - - /** - * 将假字段对象转化为集合字段值获取器 - * @param object mockBean 对象 - * @param intervalStr 区间参数 - * @return - */ - private static FieldValueGetter objectToListFieldValueGetter(MockBean object, String intervalStr) { - //创建一个方法执行者 - Invoker invoker = object::getObject; - //获取区间参数 - Integer[] integers = intervalParse(intervalStr); - //获取集合字段值获取器 - return new ListFieldValueGetter(new Invoker[]{invoker}, integers); - } - - /** - * 将假字段对象转化为数组字段值获取器 - * - * @param object - * @param intervalStr - * @return - */ - private static FieldValueGetter objectToArrayFieldValueGetter(MockBean object, String intervalStr) { - //创建一个方法执行者 - Invoker invoker = object::getObject; - - //获取区间参数 - Integer[] integers = intervalParse(intervalStr); - //获取集合字段值获取器 - return new ArrayFieldValueGetter(new Invoker[]{invoker}, integers); - } - - /** - * 解析区间参数 - * - * @param intervalStr - * @return - */ - private static Integer[] intervalParse(String intervalStr) { - if (intervalStr == null) { - //如果没有区间参数,直接返回[1,1] - return new Integer[]{1, 1}; - } else { - //有区间参数,解析 - //切割,有可能有小数位的区间 - //期望中,切割后长度最多为2 - String[] split = intervalStr.split("\\."); - //整数位的区间参数 - String integerInterval = split[0].trim(); - if (integerInterval.length() > 0) { - //如果不是空的,切割 - String[] splitIntInterval = integerInterval.split("-"); - int intervalMin = Integer.parseInt(splitIntInterval[0]); - int intervalMax = splitIntInterval.length > 1 ? Integer.parseInt(splitIntInterval[1]) : 1; - return new Integer[]{intervalMin, intervalMax}; - } else { - //如果为空,返回[1,1] - return new Integer[]{1, 1}; - } - } - } - - - /** - * 获取一个MockBean - * - * @param - * @return - */ - private static MockBean getMockBean(Class objectObject, MockField[] fields) { - //返回封装结果 - return MockBeanFactory.createMockBean(objectObject, fields); - } - - /** - * 获取一个MockBean - */ - private static MockBean getMockBean(Class objectObject, List fields) { - //返回封装结果 - return getMockBean(objectObject, fields.toArray(new MockField[0])); - } - - /** - * 获取一个MockMapBean - * - * @param fields - * @return - */ - private static MockMapBean getMockMapBean(MockField[] fields) { - return MockBeanFactory.createMockMapBean(fields); - } - - - /** - * 获取一个MockMapBean - * - * @param fields - * @return - */ - private static MockMapBean getMockMapBean(List fields) { - return getMockMapBean(fields.toArray(new MockField[0])); - } - - /** - * 获取一个map类型封装对象 - */ - private static MockBean getMockMap(MockField[] fields) { - return new MockMapBean(fields); - } - - /** - * 获取一个map类型封装对象 - */ - private static MockBean getMockMap(List fields) { - return getMockMap(fields.toArray(new MockField[0])); - } - - - /** - * 判断这个类型在预期类型中是哪一个类型的 - * - * @return - */ - private static int typeReferee(Object object) { - //String 类型,属于指令 - if (object instanceof String) { - return TYPE_STRING; - } - //Integer 类型,属于整数 - if (object instanceof Integer) { - return TYPE_INTEGER; - } - //Double 类型,属于浮点数 - if (object instanceof Double) { - return TYPE_DOUBLE; - } - //Map类型,属于一个集合类或者对象类 - if (FieldUtils.isChild(object, Map.class)) { - return TYPE_MAP; - } - //List类型,可考虑将其转化为Array类型,减少工作量 - if (FieldUtils.isChild(object, List.class)) { - return TYPE_LIST; - } - //数组类型,属于数组类 - if (object.getClass().isArray()) { - return TYPE_ARRAY; - } - //Class类型,属于直接解析类型,除非解析不到 - if(object.getClass().equals(Class.class)){ - return TYPE_CLASS; - } - //其他情况,为一个未知的Object类型 - return TYPE_OBJECT; - } - - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/ChineseUtil.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/ChineseUtil.java deleted file mode 100644 index fc1e51c..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/ChineseUtil.java +++ /dev/null @@ -1,214 +0,0 @@ -package io.fluent.mocker.utils; - - -import java.nio.charset.Charset; -import java.util.concurrent.ThreadLocalRandom; - -/** - * 获取一个随机中文姓名 代码灵感来源于网络 讲道理,效果不是特别好 而且关于字符编码的转换也不确定处理的好 - * - * @author ForteScarlet - */ -public class ChineseUtil { - -// // 初始化百家姓数据 -// static { -// byte[][] end; -// try { -// // 获取字节文件输入流 -// InputStream inStream = ChineseUtil.class.getClassLoader().getResourceAsStream("mock/surnames"); -// BufferedReader reader = new BufferedReader(new InputStreamReader(inStream)); -// // 转化为byte数组 -// String[] lines = reader.lines().filter(l -> l.trim().length() > 0).toArray(String[]::new); -// byte[][] surnameBytes = new byte[lines.length][]; -// for (int index = 0; index < lines.length; index++) { -// String l = lines[index]; -// String[] split = l.replace(";", "").split(","); -// byte[] bytes = new byte[split.length]; -// for (int i = 0; i < split.length; i++) { -// bytes[i] = Byte.parseByte(split[i]); -// } -// surnameBytes[index] = bytes; -// String s = new String(bytes, StandardCharsets.UTF_8); -// } -// end = surnameBytes; -// } catch (Exception ignored) { -// end = null; -// } -// -// SURNAME_BYTES = end; -// } -// /** -// * 百家姓对应的字节 -// */ -// private static final byte[][] SURNAME_BYTES; - - private static final Charset GBK = Charset.forName("GBK"); - -// public static final Charset UTF_8 = StandardCharsets.UTF_8; - - /** - * 百家姓 - */ - private static String[] Surname = {"赵", "钱", "孙", "李", "周", "吴", "郑", "王", "冯", "陈", "褚", "卫", "蒋", "沈", "韩", "杨", - "朱", "秦", "尤", "许", "何", "吕", "施", "张", "孔", "曹", "严", "华", "金", "魏", "陶", "姜", "戚", "谢", "邹", "喻", "柏", - "水", "窦", "章", "云", "苏", "潘", "葛", "奚", "范", "彭", "郎", "鲁", "韦", "昌", "马", "苗", "凤", "花", "方", "俞", "任", - "袁", "柳", "酆", "鲍", "史", "唐", "费", "廉", "岑", "薛", "雷", "贺", "倪", "汤", "滕", "殷", "罗", "毕", "郝", "邬", "安", - "常", "乐", "于", "时", "傅", "皮", "卞", "齐", "康", "伍", "余", "元", "卜", "顾", "孟", "平", "黄", "和", "穆", "萧", "尹", - "姚", "邵", "湛", "汪", "祁", "毛", "禹", "狄", "米", "贝", "明", "臧", "计", "伏", "成", "戴", "谈", "宋", "茅", "庞", "熊", - "纪", "舒", "屈", "项", "祝", "董", "梁", "杜", "阮", "蓝", "闵", "席", "季", "麻", "强", "贾", "路", "娄", "危", "江", "童", - "颜", "郭", "梅", "盛", "林", "刁", "钟", "徐", "邱", "骆", "高", "夏", "蔡", "田", "樊", "胡", "凌", "霍", "虞", "万", "支", - "柯", "昝", "管", "卢", "莫", "经", "房", "裘", "缪", "干", "解", "应", "宗", "丁", "宣", "贲", "邓", "郁", "单", "杭", "洪", - "包", "诸", "左", "石", "崔", "吉", "钮", "龚", "程", "嵇", "邢", "滑", "裴", "陆", "荣", "翁", "荀", "羊", "于", "惠", "甄", - "曲", "家", "封", "芮", "羿", "储", "靳", "汲", "邴", "糜", "松", "井", "段", "富", "巫", "乌", "焦", "巴", "弓", "牧", "隗", - "山", "谷", "车", "侯", "宓", "蓬", "全", "郗", "班", "仰", "秋", "仲", "伊", "宫", "宁", "仇", "栾", "暴", "甘", "钭", "厉", - "戎", "祖", "武", "符", "刘", "景", "詹", "束", "龙", "叶", "幸", "司", "韶", "郜", "黎", "蓟", "溥", "印", "宿", "白", "怀", - "蒲", "邰", "从", "鄂", "索", "咸", "籍", "赖", "卓", "蔺", "屠", "蒙", "池", "乔", "阴", "郁", "胥", "能", "苍", "双", "闻", - "莘", "党", "翟", "谭", "贡", "劳", "逄", "姬", "申", "扶", "堵", "冉", "宰", "郦", "雍", "却", "璩", "桑", "桂", "濮", "牛", - "寿", "通", "边", "扈", "燕", "冀", "浦", "尚", "农", "温", "别", "庄", "晏", "柴", "瞿", "阎", "充", "慕", "连", "茹", "习", - "宦", "艾", "鱼", "容", "向", "古", "易", "慎", "戈", "廖", "庾", "终", "暨", "居", "衡", "步", "都", "耿", "满", "弘", "匡", - "国", "文", "寇", "广", "禄", "阙", "东", "欧", "殳", "沃", "利", "蔚", "越", "夔", "隆", "师", "巩", "厍", "聂", "晁", "勾", - "敖", "融", "冷", "訾", "辛", "阚", "那", "简", "饶", "空", "曾", "毋", "沙", "乜", "养", "鞠", "须", "丰", "巢", "关", "蒯", - "相", "查", "后", "荆", "红", "游", "郏", "竺", "权", "逯", "盖", "益", "桓", "公", "仉", "督", "岳", "帅", "缑", "亢", "况", - "郈", "有", "琴", "归", "海", "晋", "楚", "闫", "法", "汝", "鄢", "涂", "钦", "商", "牟", "佘", "佴", "伯", "赏", "墨", "哈", - "谯", "篁", "年", "爱", "阳", "佟", "言", "福", "南", "火", "铁", "迟", "漆", "官", "冼", "真", "展", "繁", "檀", "祭", "密", - "敬", "揭", "舜", "楼", "疏", "冒", "浑", "挚", "胶", "随", "高", "皋", "原", "种", "练", "弥", "仓", "眭", "蹇", "覃", "阿", - "门", "恽", "来", "綦", "召", "仪", "风", "介", "巨", "木", "京", "狐", "郇", "虎", "枚", "抗", "达", "杞", "苌", "折", "麦", - "庆", "过", "竹", "端", "鲜", "皇", "亓", "老", "是", "秘", "畅", "邝", "还", "宾", "闾", "辜", "纵", "侴", "万俟", "司马", "上官", - "欧阳", "夏侯", "诸葛", "闻人", "东方", "赫连", "皇甫", "羊舌", "尉迟", "公羊", "澹台", "公冶", "宗正", "濮阳", "淳于", "单于", "太叔", "申屠", - "公孙", "仲孙", "轩辕", "令狐", "钟离", "宇文", "长孙", "慕容", "鲜于", "闾丘", "司徒", "司空", "兀官", "司寇", "南门", "呼延", "子车", "颛孙", - "端木", "巫马", "公西", "漆雕", "车正", "壤驷", "公良", "拓跋", "夹谷", "宰父", "谷梁", "段干", "百里", "东郭", "微生", "梁丘", "左丘", "东门", - "西门", "南宫", "第五", "公仪", "公乘", "太史", "仲长", "叔孙", "屈突", "尔朱", "东乡", "相里", "胡母", "司城", "张廖", "雍门", "毋丘", "贺兰", - "綦毋", "屋庐", "独孤", "南郭", "北宫", "王孙"}; - - - - /** - * 获取一个随机姓名 - * @see #getName() - */ - @Deprecated - public static String getName(String charsetName) { - return getName(Charset.forName(charsetName)); - } - /** - * 获取一个随机姓名 - * @see #getName() - */ - @Deprecated - public static String getName(Charset charset) { - return getName(); - } - - /** - * 获得多个随机姓氏 - */ - public static String[] getFamilyName(int nums) { - String[] names = new String[nums]; - - int index; - for (int i = 0; i < nums; i++) { - // 获得一个随机的姓氏 - index = RandomUtil.getRandom().nextInt(Surname.length); - names[i] = Surname[index]; - } - - return names; - } - - /** - * 获得一个随机姓氏 - */ - public static String getFamilyName() { - return Surname[RandomUtil.getRandom().nextInt(Surname.length)]; - } - - /** - * 获取一个随机姓名 - */ - public static String getName() { - ThreadLocalRandom random = RandomUtil.getRandom(); - - // 获得一个随机的姓氏 - boolean two = random.nextBoolean(); - StringBuilder nameBuilder = new StringBuilder(1 + (two ? 2 : 1)).append(getFamilyName()); - /* 从常用字中选取一个或两个字作为名 */ - if (two) { - nameBuilder.append(getChinese()).append(getChinese()); - } else { - nameBuilder.append(getChinese()); - } - return nameBuilder.toString(); - } - - - /** - * 获取一个随机汉字 - * 指定编码已失效,理论上应该不需要指定编码 - * @see #getName() - */ - @Deprecated - public static String getChinese(String encoding) { - return getChinese(Charset.forName(encoding)); - } - - /** - * 获取一个汉字 - * 理论上应该不需要指定编码 - * @see #getName() - * - */ - @Deprecated - public static String getChinese(Charset charset) { - return getChinese(); - } - - /** - * 获取一个随机汉字 - */ - public static String getChinese() { - ThreadLocalRandom random = RandomUtil.getRandom(); - byte[] bArr = new byte[2]; - //区码,0xA0打头,从第16区开始,即0xB0=11*16=176,16~55一级汉字,56~87二级汉字 - // 176 ~ random(0~39) - bArr[0] = (byte) random.nextInt(176, 176 + 39); - //位码,0xA0打头,范围第1~94列 - // 161 ~ random(0~92) - bArr[1] = (byte) random.nextInt(161, 161 + 93); - // 区位码组合成汉字 - return new String(bArr, GBK); - } - - /** - * 获取一个随机汉字 - */ - public static String getChinese(int num) { - StringBuilder sb = new StringBuilder(num); - for (int i = 0; i < num; i++) { - sb.append(getChinese()); - } - return sb.toString(); - } - - /** - * 获取一个随机汉字 - * @see #getChinese(int) - */ - @Deprecated - public static String getChinese(int num, String encoding) { - return getChinese(num); - } - /** - * 获取一个随机汉字 - * @see #getChinese(int) - */ - @Deprecated - public static String getChinese(int num, Charset charset) { - return getChinese(num); - } - - /** - * 构造私有化 构造方法 - */ - private ChineseUtil() { } -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/ClassScanner.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/ClassScanner.java deleted file mode 100644 index f780585..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/ClassScanner.java +++ /dev/null @@ -1,187 +0,0 @@ -package io.fluent.mocker.utils; - - -import java.io.File; -import java.io.IOException; -import java.net.JarURLConnection; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.*; -import java.util.function.Predicate; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; - - -/** - * 扫描包下路径 - * 包括本地文件和jar包文件 - * - * @author ljb - */ -public class ClassScanner { - - /** - * 储存结果的Set集合 - */ - private Set> eleStrategySet = new HashSet<>(); - - /** - * 默认使用的类加载器 - */ - private ClassLoader classLoader; - - /** - * 构造,使用当前类所在的加载器 - */ - public ClassScanner() { - //默认使用的类加载器 - this.classLoader = ClassScanner.class.getClassLoader(); - } - - /** - * 构造,提供一个类加载器 - * - * @param classLoader 类加载器 - */ - public ClassScanner(ClassLoader classLoader) { - Objects.requireNonNull(classLoader); - this.classLoader = classLoader; - } - - /** - * 根据过滤规则查询 - * - * @param classFilter class过滤规则 - * @throws ClassNotFoundException - */ - public ClassScanner find(String packageName, Predicate> classFilter) throws ClassNotFoundException, IOException, URISyntaxException { - eleStrategySet.addAll(addClass(packageName, classFilter)); - return this; - } - - /** - * 查询全部 - * @throws ClassNotFoundException - * @throws IOException - * @throws URISyntaxException - */ - public ClassScanner find(String packageName) throws ClassNotFoundException, IOException, URISyntaxException { - eleStrategySet.addAll(addClass(packageName, c -> true)); - return this; - } - - /** - * 获取包下所有实现了superStrategy的类并加入list - * - * @param classFilter class过滤器 - */ - private Set> addClass(String packageName, Predicate> classFilter) throws ClassNotFoundException, URISyntaxException, IOException { - final String path = packageName.replace(".", "/"); - URL url = classLoader.getResource(path); - //如果路径为null,抛出异常 - if (url == null) { - throw new RuntimeException("package url not exists: " + packageName); - } - - //路径字符串 - String protocol = url.getProtocol(); - //如果是文件类型,使用文件扫描 - if ("file".equals(protocol)) { - // 本地自己可见的代码 - return findClassLocal(packageName, classFilter); - //如果是jar包类型,使用jar包扫描 - } else if ("jar".equals(protocol)) { - // 引用jar包的代码 - return findClassJar(packageName, classFilter); - } - return Collections.emptySet(); - } - - /** - * 本地查找 - */ - private Set> findClassLocal(final String packName, final Predicate> classFilter) throws URISyntaxException { - Set> set = new HashSet<>(); - URI url = classLoader.getResource(packName.replace(".", "/")).toURI(); - - File file = new File(url); - final File[] files = file.listFiles(); - if (files != null) { - for (File chiFile : files) { - if (chiFile.isDirectory()) { - //如果是文件夹,递归扫描 - set.addAll(findClassLocal(packName + "." + chiFile.getName(), classFilter)); - } - if (chiFile.getName().endsWith(".class")) { - Class clazz = null; - try { - clazz = classLoader.loadClass(packName + "." + chiFile.getName().replace(".class", "")); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - if (clazz != null && classFilter.test(clazz)) { - set.add(clazz); - } - } - } - } - - return set; - } - - /** - * jar包查找 - */ - private Set> findClassJar(final String packName, final Predicate> classFilter) throws ClassNotFoundException, IOException { - Set> set = new HashSet<>(); - String pathName = packName.replace(".", "/"); - JarFile jarFile; - URL url = classLoader.getResource(pathName); - JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection(); - jarFile = jarURLConnection.getJarFile(); - - Enumeration jarEntries = jarFile.entries(); - while (jarEntries.hasMoreElements()) { - JarEntry jarEntry = jarEntries.nextElement(); - String jarEntryName = jarEntry.getName(); - - if (jarEntryName.contains(pathName) && !jarEntryName.equals(pathName + "/")) { - //递归遍历子目录 - if (jarEntry.isDirectory()) { - String clazzName = jarEntry.getName().replace("/", "."); - int endIndex = clazzName.lastIndexOf("."); - String prefix = null; - if (endIndex > 0) { - prefix = clazzName.substring(0, endIndex); - } - set.addAll(findClassJar(prefix, classFilter)); - } - if (jarEntry.getName().endsWith(".class")) { - Class clazz = null; - clazz = classLoader.loadClass(jarEntry.getName().replace("/", ".").replace(".class", "")); - //判断,如果符合,添加 - if (clazz != null && classFilter.test(clazz)) { - set.add(clazz); - } - } - } - } - return set; - } - - /** - * 获取当前扫描到的结果 - */ - public Set> get() { - return new HashSet<>(this.eleStrategySet); - } - - /** - * 清空当前扫描结果集 - */ - public void clear(){ - this.eleStrategySet.clear(); - } - -} \ No newline at end of file diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/CollectorUtil.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/CollectorUtil.java deleted file mode 100644 index f3b40c9..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/CollectorUtil.java +++ /dev/null @@ -1,54 +0,0 @@ -package io.fluent.mocker.utils; - -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collector; - -/** - * - * 针对{@link Collector}的操作工具类 - * - * @author ForteScarlet - * @date 2020/8/1 - */ -public class CollectorUtil { - - /** - * 在非stream环境下使用{@link Collector} - * @param num 获取数量 - * @param getter 单值获取器 - * @param collector 收集器 - */ - public static R collector(int num, Supplier getter, Collector collector){ - // 获取容器 - A container = collector.supplier().get(); - // 获取累加器 - BiConsumer accumulator = collector.accumulator(); - for (int i = 0; i < num; i++) { - accumulator.accept(container, getter.get()); - } - // 获取结果 - return collector.finisher().apply(container); - } - - /** - * 在非stream环境下使用{@link Collector} - * @param num 获取数量 - * @param getter 单值获取器 - * @param mapper 转化器 - * @param collector 收集器 - */ - public static N collector(int num, Supplier getter, Function mapper, Collector collector){ - // 获取容器 - A container = collector.supplier().get(); - // 获取累加器 - BiConsumer accumulator = collector.accumulator(); - for (int i = 0; i < num; i++) { - accumulator.accept(container, mapper.apply(getter.get())); - } - // 获取结果 - return collector.finisher().apply(container); - } - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/FieldUtils.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/FieldUtils.java deleted file mode 100644 index 817126d..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/FieldUtils.java +++ /dev/null @@ -1,2073 +0,0 @@ -package io.fluent.mocker.utils; - - - - -import java.lang.reflect.*; -import java.util.*; -import java.util.stream.Collectors; - -/** - *

- * 字段操作工具,提供丰富的方法,以反射的方式从对象中获取值或赋值。
- * 其中:
- * - objectGetter方法可以允许使用多级字段,例如"user.child.name"
- * - getExcelNum方法可以获取Excel中列的数字坐标,例如:"AA" => 27
- *

- *
- *

- * 实现了缓存优化,使得效率大幅上升 - * 由于希望将其作为一个简单的工具类使用,因此全部使用内部类实现 - *

- *

2018-12-15 多层级缓存优化-getter测试结果:

- *
- * 次数:500w
- * 深度:100
- * -没有缓存的:
- *      - * >总用时:1635s ; 1635950ms
- *      - * >平均用时:.33ms
- * -有缓存的:
- *      - * >总用时:18s ; 18216ms
- *      - * >平均用时:.00ms
- *
- *
- *
- *
- *

2018-12-15至2018-12-16 多层级缓存优化-getter测试结果:

- *
- * 次数:5亿
- * 深度:200
- * -没有缓存的:
- *      - * >总用时:至终止程序为止,用时11 小时 50 分 13 秒 - *      - * >控制台可见进度:6.89%左右 - *      - * >未执行完成,中途终止 - * -有缓存的:
- *      - * >总用时:3433s ; 3433008ms - * - *
- *
- *

- * - * @author ForteScarlet - */ -public class FieldUtils { - - - //静态代码块加载字母顺序 - static { - - Map wordNum = new HashMap<>(); - - for (int i = 1; i <= 26; i++) { - char c = (char) (97 + (i - 1)); - wordNum.put(c + "", i); - } - - //获取字母顺序表 - //保存 - WORD_NUMBER = wordNum; - - } - - /** - * 字母顺序表 - */ - private static final Map WORD_NUMBER; - - /** - * 单层字段缓存记录,使用线程安全map - */ - private static final Map> SINGLE_FIELD_CACHE_MAP = Collections.synchronizedMap(new HashMap<>()); - - /** - * 多层字段缓存记录,使用线程安全map - */ - private static final Map> LEVEL_FIELD_CACHE_MAP = Collections.synchronizedMap(new HashMap<>()); - - - /** - * 获取Excel中列的数字坐标
- * 例如:"AA" => 27 - * - * @param colStr Excel中的列坐标 - * @return 此列坐标对应的数字 - * @author ForteScarlet - */ - public static long getExcelNum(String colStr) { - //获取数组 - char[] array = colStr.toCharArray(); - //长度 - int length = array.length; - //初始数 - long end = 1; - - //倒序遍历,从小位开始遍历 - for (int i = array.length - 1; i >= 0; i--) { - //字母序号 - int num = WORD_NUMBER.get((array[i] + "").toLowerCase()); - //加成 - int addBuffer = length - i - 1; - //结果加成 - end += num * (int) (Math.pow(26, addBuffer)); - } - - //返回结果 - return end; - } - - /** - * 获取对象的所有字段(包括没有get方法的字段) - * - * @param tClass 对象 - * @return - * @author ForteScarlet - */ - public static List getFieldsWithoutGetter(Class tClass) { - Field[] fs = tClass.getDeclaredFields(); - return Arrays.asList(fs); - } - - - /** - * 获取对象的所有字段(包括没有get方法的字段) - * @param t - * @param - * @return - */ - public static List getFieldsWithoutGetter(T t) { - return getFieldsWithoutGetter(t.getClass()); - } - - - /** - * 获取对象的所有字段名(包括没有get方法的字段) - * @param t 对象 - * @return - * @author ForteScarlet - */ - public static List getFieldsNameWithoutGetter(T t) { - return getFieldsWithoutGetter(t).stream().map(Field::getName).collect(Collectors.toList()); - } - - /** - * 获取对象的所有字段 - * @param tClass 对象 - * @return - * @author ForteScarlet - */ - public static List getFieldsWithGetter(Class tClass) { - Field[] fs = tClass.getDeclaredFields(); - //返回时过滤掉没有get方法的字段 - return Arrays.stream(fs).filter(f -> Arrays.stream(tClass.getMethods()).anyMatch(m -> m.getName().equals("get" + headUpper(f.getName())))).collect(Collectors.toList()); - } - - /** - * 获取对象的所有字段 - * - * @param t - * @param - * @return - */ - public static List getFieldsWithGetter(T t) { - return getFieldsWithGetter(t.getClass()); - } - - /** - * 获取对象的所有字段名 - * - * @param t 对象 - * @return - * @author ForteScarlet - */ - public static List getFieldsNameWithGetter(T t) { - return getFieldsWithGetter(t).stream().map(Field::getName).collect(Collectors.toList()); - } - - - /** - * 获取类指定的字段对象,支持多层级获取 - * @param c - * @param fieldName - * @return - */ - public static Field fieldGetter(Class c , String fieldName){ - //先进行缓存判断,如果缓存中有记录,直接返回 - CacheField cacheField = getCacheField(c, fieldName); - if(cacheField != null){ - return cacheField.getField(); - } - - //可以获取多级字段的字段对象 - //使用'.'切割字段名 - String[] split = fieldName.split("\\."); - if(split.length == 1){ - //如果长度为1,则说明只有一级字段,直接获取字段对象 - return getField(c , fieldName); - }else{ - //如果不是1,则说明不止1层字段值 - //当前字段名 - String thisFieldName = split[0]; - //剩下的字段名称拼接 - //移除第一个字段 - List list = Arrays.stream(split).collect(Collectors.toList()); - list.remove(0); - //拼接剩余 - String otherFieldName = String.join(".", list); - //递归获取 - //多层级也计入缓存 - Field field = fieldGetter(getFieldClass(c, thisFieldName), otherFieldName); - //计入缓存 - saveSingleCacheField(c , field , null , null); - return field; - } - } - - /** - * 获取字段的class类型,支持多层级获取 - * @param c - * @param fieldName - * @return - */ - public static Class fieldClassGetter(Class c , String fieldName){ - return fieldGetter(c , fieldName).getType(); - } - - - /** - * 获取字段的getter方法,单层级 - * @param whereIn - * @param fieldName - * @return - */ - public static Method getFieldGetter(Class whereIn , String fieldName){ - //先查询缓存 - Method cacheGetter = getCacheFieldGetter(whereIn, fieldName); - if(cacheGetter != null){ - return cacheGetter; - } - - //获取getter方法 - try { - Method getter = whereIn.getMethod("get" + headUpper(fieldName)); - //计入缓存 - saveSingleCacheFieldGetter(whereIn , fieldName , getter); - //返回结果 - return getter; - } catch (NoSuchMethodException e) { - //如果出现异常,返回null - return null; - } - } - - /** - * 获取字段的getter方法 - * @param whereIn - * 字段所在类 - * @param field - * 字段 - * @return - */ - public static Method getFieldGetter(Class whereIn , Field field){ - //获取getter方法 - return getFieldGetter(whereIn , field.getName()); - } - - /** - * 获取字段的getter方法 - * @param obj - * @param field - * @return - */ - public static Method getFieldGetter(Object obj, Field field){ - return getFieldGetter(obj.getClass() , field); - } - - - /** - * 获取字段的getter方法 - * @param obj - * @param fieldName - * @return - */ - public static Method getFieldGetter(Object obj, String fieldName){ - return getFieldGetter(obj.getClass() , fieldName); - } - - - /** - * 获取字段的setter方法 - * @param whereIn - * @param fieldName - * @return - */ - public static Method getFieldSetter(Class whereIn , String fieldName){ - //先查询缓存中是否存在 - Method cacheSetter = getCacheFieldSetter(whereIn, fieldName); - if(cacheSetter != null){ - return cacheSetter; - } - - - try { - //获取这个字段的Field对象 - Field field = getField(whereIn, fieldName); - // whereIn.getDeclaredField(fieldName); - Method setter = whereIn.getMethod("set" + headUpper(fieldName), field.getType()); - //计入缓存 - saveSingleCacheFieldSetter(whereIn , fieldName , setter); - //返回 - return setter; - } catch (NoSuchMethodException e) { -// e.printStackTrace(); - //如果出现异常,返回null - return null; - } - } - - /** - * 获取字段的setter方法 - * @param whereIn - * @param field - * @return - */ - public static Method getFieldSetter(Class whereIn , Field field){ - //先查询缓存 - Method cacheFieldSetter = getCacheFieldSetter(whereIn, field.getName()); - if(cacheFieldSetter != null){ - return cacheFieldSetter; - } - - try { - // a public method - Method setter = whereIn.getMethod("set" + headUpper(field.getName()), field.getType()); - //计入缓存 - saveSingleCacheFieldSetter(whereIn , field , setter); - //返回结果 - return setter; - } catch (NoSuchMethodException e) { - //如果出现异常,返回null - return null; - } - } - - /** - * 获取字段的setter方法 - * @param obj - * @param fieldName - * @return - */ - public static Method getFieldSetter(Object obj , String fieldName){ - return getFieldSetter(obj.getClass() , fieldName); - } - - /** - * 获取字段的setter方法 - * @param obj - * @param field - * @return - */ - public static Method getFieldSetter(Object obj , Field field){ - return getFieldSetter(obj.getClass() , field); - } - - - /** - * 获取字段的getter方法,支持多层级获取 - * @param objClass - * @param fieldName - * @return - * @throws NoSuchMethodException - */ - public static Method fieldGetterGetter(Class objClass, String fieldName) throws NoSuchMethodException { - //判断是否有用“.”分割 - String[] split = fieldName.split("\\."); - //如果分割后只有一个字段值,说明是单层 - if (split.length == 1) { - //获取其get方法,返回执行结果 - Method getter = getFieldGetter(objClass , fieldName); - if(getter == null){ - //抛出没有此方法异常 - throw new NoSuchMethodException("没有找到类["+ objClass +"]字段["+ fieldName +"]的getter方法"); - } - //返回获取结果 - return getter; - }else{ - //否则为多层级,深入获取 - //获取第一个字段名,拼接其余字段名并进行递归处理 - String field = split[0]; - //移除第一个字段 - List list = Arrays.stream(split).collect(Collectors.toList()); - list.remove(0); - //拼接剩余 - String innerFieldName = String.join(".", list); - - //递归 - return fieldGetterGetter(fieldGetterGetter(objClass, field).getReturnType(), innerFieldName); - } - } - - /** - * 通过对象的getter获取字段数值 - * 支持类似“user.child”这种多层级的获取方式 - * 获取的字段必须有其对应的公共get方法 - * @param t - * @param fieldName - * @return - * @throws IllegalAccessException - * @throws NoSuchMethodException - * @throws InvocationTargetException - */ - public static Object objectGetter(Object t, String fieldName) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - return objectGetter(t , t , fieldName , fieldName , 1); - } - - /** - * 通过对象的getter获取字段数值 - * 支持类似“user.child”这种多层级的获取方式 - * 获取的字段必须有其对应的公共get方法 - * @param t - * 被获取的对象 - * @param fieldName - * 字段名 - * @return - * @throws SecurityException - * @throws InvocationTargetException - * @throws IllegalArgumentException - * @throws IllegalAccessException - * @author ForteScarlet - */ - private static Object objectGetter(Object t, Object root, String fieldName, String realFieldName, int level) throws SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { - - //先查询缓存 - CacheField cacheField = getCacheField(t.getClass(), fieldName); - if(cacheField != null){ - //如果有缓存,获取执行结果 - InvokeResult invokeResult = cacheField.fieldValue(t); - boolean success = invokeResult.isSuccess(); - if(success){ - return invokeResult.getInvoke(); - } - } - - //判断是否有用“.”分割 - String[] split = fieldName.split("\\."); - //如果分割后只有一个字段值,直接返回 - if (split.length == 1) { - - //获取其get方法,返回执行结果 - Method getter = getFieldGetter(t , fieldName); - if(getter == null){ - //抛出没有此方法异常 - throw new NoSuchMethodException("没有找到类["+ t.getClass() +"]字段["+ fieldName +"]的getter方法"); - } - //计入单缓存-当前 - SingleCacheField singleCacheField = saveSingleCacheFieldGetter(t.getClass(), fieldName, getter); - - //如果层数等级与真实字段相同且等级不为1,说明这是多层级字段的最终字段,保存 - if(level != 1 && level == realFieldName.split("\\.").length){ - saveLevelCacheField(root.getClass() , realFieldName , singleCacheField); - } - - - //返回执行结果 - return getter.invoke(t); - } else { - //否则为多层级字段,获取第一个字段名,拼接其余字段名并进行递归处理 - String field = split[0]; - //移除第一个字段 - List list = Arrays.stream(split).collect(Collectors.toList()); - list.remove(0); - //拼接剩余 - String innerFieldName = String.join(".", list); - - - /* - 以下的getter获取方法均为当前字段的,即field字段 - */ - - //获取其get方法,返回执行结果 - Method getter = getFieldGetter(t , field); - if(getter == null){ - //抛出没有此方法异常 - throw new NoSuchMethodException("没有找到类["+ t.getClass() +"]字段["+ field +"]的getter方法"); - } - - //计入单缓存-当前-同时将getter方法提前计入缓存 - SingleCacheField singleCacheField = saveSingleCacheFieldGetter(t.getClass(), field, getter); - - - //此字段的实例对象-直接使用与上面相同的方式获取执行结果而不是使用自我调用 - Object innerObject = getter.invoke(t); - - /* - 保存此多层级字段的getter并保存至多层级缓存 - 假如目标是 bean.bean.bean.a - 则当前第一轮为 - realField: bean.bean.bean.a - field: bean - innerField: bean.bean.a - 则计入多层缓存的应当是bean - - 第二轮为 - realField: bean.bean.bean.a - field: bean - innerField: bean.a - 则计入多层缓存的应当是bean.bean - - 可见应记录层数,并截取与层数相同数量的字段层级并进行记录 - 层数默认开始为1 - */ -// //计入多层级缓存-当前 - //获取字段名-切割真实字段名 - String levelFieldName = Arrays.stream(realFieldName.split("\\.")).limit(level).collect(Collectors.joining(".")); - saveLevelCacheField(root.getClass() , levelFieldName , singleCacheField); - - - - //field必定为单层字段,获取field对应的对象,然后使用此对象进行递归 - return objectGetter(innerObject, root, innerFieldName, realFieldName, level+1); - } - } - - - - /** - * 通过对象的setter为字段赋值 - * 支持类似“user.child”这种多层级的赋值方式 - * 赋值的字段必须有其对应的公共set方法 - * 如果多层级对象中有非底层级字段为null,将会尝试为其创建一个新的实例 - * - * TODO 旧 - * - * @param t 对象 - * @param fieldName 需要赋值的字段 - * @param value 需要赋的值 - * @throws InvocationTargetException - * @throws IllegalAccessException - */ - public static void objectSetter(Object t, String fieldName, Object value) throws Exception { - //判断是否有用“.”分割 - String[] split = fieldName.split("\\."); - //如果分割后只有一个字段值,直接进行赋值 - if (split.length == 1) { - //获取其set方法,返回执行结果 - String setterName = "set" + FieldUtils.headUpper(fieldName); - //获取字段的setter方法 - Method setter = getFieldSetter(t , fieldName); - //如果没有setter,展示异常提醒 - // 直接抛出异常 - if(setter == null){ - String error = "没有找到["+ t.getClass() +"]中的字段["+ fieldName +"]的setter["+ setterName +"]方法,无法进行赋值"; - throw new RuntimeException(new NoSuchFieldException(error)); - }else{ - //赋值 - MethodUtil.invoke(t , new Object[]{value} , setter); - } - - } else { - //否则为多层级字段,获取第一个字段名,拼接其余字段名并进行递归处理 - String field = split[0]; - //移除第一个字段 - List list = Arrays.stream(split).collect(Collectors.toList()); - list.remove(0); - //拼接剩余 - fieldName = String.join(".", list); - - //获取下一层的对象 - Object fieldObject = objectGetter(t, field); - if (fieldObject == null) { - //如果为null,创建一个此类型的实例 - fieldObject = getFieldClass(t, field).newInstance(); - //并为此对象赋值 - objectSetter(t, field, fieldObject); - } - //寻找下一层字段 - objectSetter(fieldObject, fieldName, value); - } - } - - /** - * 通过对象的setter为字段赋值 - * 支持类似“user.child”这种多层级的赋值方式 - * 赋值的字段必须有其对应的公共set方法 - * 如果多层级对象中有非底层级字段为null,将会尝试为其创建一个新的实例 - * @param t - * @param fieldName - * @param param - * @throws NoSuchMethodException - * @throws InstantiationException - * @throws IllegalAccessException - * @throws InvocationTargetException - */ - public static void objectSetter2(Object t, String fieldName, Object param) throws Exception { - // TODO 发现bug,此方法会导致缓存无法储存 - objectSetter(t , t , fieldName , fieldName , 1 , param); - } - - /** - * 通过对象的setter为字段赋值 - * 支持类似“user.child”这种多层级的赋值方式 - * 赋值的字段必须有其对应的公共set方法 - * 如果多层级对象中有非底层级字段为null,将会尝试为其创建一个新的实例 - * @param t - * @param root - * @param fieldName - * @param realFieldName - * @param level - * @param param - */ - private static void objectSetter(Object t, Object root, String fieldName, String realFieldName, int level, Object param) throws Exception { - // TODO 实现缓存的setter方法 - // TODO 存在严重bug,此方法会导致缓存无法储存和获取,导致getter效率大幅度下降 - //先查询缓存 - CacheField cacheField = getCacheField(t.getClass(), fieldName); - if(cacheField != null){ - //如果有缓存,获取执行结果 - InvokeResult invokeResult = cacheField.fieldValueSet(t, param); - if(invokeResult.isSuccess()){ - //如果赋值成功,结束方法 - return; - } - } - //判断是否有用“.”分割 - String[] split = fieldName.split("\\."); - //如果分割后只有一个字段值,直接进行赋值 - if(split.length == 1){ - //单层字段,获取setter方法 - Method setter = getFieldSetter(t, fieldName); - if(setter == null){ - //如果没有setter,抛出异常 - throw new NoSuchMethodException("没有找到类["+ t.getClass() +"]字段["+ fieldName +"]的setter方法"); - } - - - //如果有此方法,计入缓存-当前 - SingleCacheField singleCacheField = saveSingleCacheFieldSetter(t.getClass(), fieldName, setter); - //如果层数等级与真实字段相同且等级不为1,说明这是多层级字段的最终字段,保存 - if(level != 1 && level == realFieldName.split("\\.").length){ - saveLevelCacheField(root.getClass() , realFieldName , singleCacheField); - } - - //执行赋值 - MethodUtil.invoke(t, new Object[]{param}, setter); - }else{ - //否则为多层字段,获取第一个字段名 - String field = split[0]; - //移除第一个字段 - List list = Arrays.stream(split).collect(Collectors.toList()); - list.remove(0); - //拼接剩余 - String newFieldName = String.join(".", list); - - - /* - 以下的setter获取方法均为当前字段的,即field字段 - */ - - //获取其get方法和set方法,返回执行结果 - //获取setter方法 - Method setter = getFieldSetter(t , field); - if(setter == null){ - //抛出没有此方法异常 - throw new NoSuchMethodException("没有找到类["+ t.getClass() +"]字段["+ field +"]的setter方法"); - } - - //计入单缓存-当前-同时将setter方法提前计入缓存 - SingleCacheField singleCacheField = saveSingleCacheFieldSetter(t.getClass(), field, setter); - - //获取此字段的实例对象,使用objectGetter方法,可以省去一部计入缓存的步骤 - Object fieldInstance = objectGetter(t, field); - - //如果当前字段的值为null,赋值 - if(fieldInstance == null){ - fieldInstance = getFieldClass(t, field).newInstance(); - //为当前字段对象赋一个新的值 - objectSetter(t, field, fieldInstance); - - } - - //将setter计入缓存 - //计入多层级缓存-当前 - //获取字段名-切割真实字段名 - String levelFieldName = Arrays.stream(realFieldName.split("\\.")).limit(level).collect(Collectors.joining(".")); - saveLevelCacheField(root.getClass() , levelFieldName , singleCacheField); - - - //寻找下一层字段 - objectSetter(fieldInstance, root, newFieldName, realFieldName, level+1, param); - - } - - } - - - - /** - * 获取对象指定字段对象 - * - * @param object 对象的class对象 - * @param fieldName 字段名称 - */ - public static Field getField(Object object, String fieldName) { - return getField(object.getClass(), fieldName); - } - - - /** - * 获取类指定字段对象 - * - * @param objectClass 类的class对象 - * @param fieldName 字段名称 - */ - public static Field getField(Class objectClass, String fieldName) { - //反射获取全部字段 - Field[] declaredFields = objectClass.getDeclaredFields(); - //遍历寻找此字段 - Field field = null; - for (Field f : declaredFields) { - //如果找到了,赋值并跳出循环 - if (f.getName().equals(fieldName)) { - field = f; - break; - } - } - - if(field == null){ - Class parent = objectClass.getSuperclass(); - if(parent != null && !parent.equals(Object.class)){ - field = getField(parent, fieldName); - } - } - - return field; - } - - - /** - * 获取指定类字段的类型class对象 - * - * @param objectClass 类class对象 - * @param fieldName 字段名称 - */ - public static Class getFieldClass(Class objectClass, String fieldName) { - return getField(objectClass, fieldName).getType(); - } - - /** - * 获取类指定字段的class对象 - * - * @param object 类实例 - * @param fieldName 字段名称 - * @return - */ - public static Class getFieldClass(Object object, String fieldName) { - return getFieldClass(object.getClass(), fieldName); - } - - - /** - * 通过Class对象判断是否存在此字段 - * - * @param tClass - * @param field - * @return - */ - public static boolean isFieldExist(Class tClass, String field) { - //判断是否为多层级字段 - String[] split = field.split("\\."); - if (split.length == 1) { - //如果只有一个,直接获取 - Field getField = getField(tClass, field); -// try { -// getField = ; -// getField = tClass.getDeclaredField(field); -// } catch (NoSuchFieldException ignored) { -// } - //如果存在,返回true,否则返回false - return getField != null; - } else { - //否则,存在多层级字段,先获取第一个字段并获得其类型,然后通过此类型的Class对象进一步判断 - String firstField = split[0]; - //获取字段对象 - Field getField = null; - try { - getField = tClass.getDeclaredField(firstField); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - } - //如果获取失败,直接返回false - if (getField == null) { - return false; - } - - Class firstFieldType = getField.getType(); - //拼接剩余 - //移除第一个字段 - List list = Arrays.stream(split).collect(Collectors.toList()); - list.remove(0); - //拼接剩余 - String fieldName = list.stream().collect(Collectors.joining(".")); - //获取当前字段的Class对象 - Class fieldClass = getFieldClass(tClass, firstField); - //递归 - return isFieldExist(fieldClass, fieldName); - } - } - - /** - * 通过对象实例判断字段是否存在 - * - * @param obj 实例对象 - * @param field 查询字段 - * @return - * @throws NoSuchFieldException - */ - public static boolean isFieldExist(Object obj, String field) { - return isFieldExist(obj.getClass(), field); - } - - - - - - - /** - * 获取一个list字段的泛型类型
- * 这个字段必须是一个list类型的字段! - * @param listField 字段 - * @return - * @throws ClassNotFoundException - */ - public static Class getListFieldGeneric(Field listField) { - - ParameterizedType listGenericType = (ParameterizedType) listField.getGenericType(); - Type[] listActualTypeArguments = listGenericType.getActualTypeArguments(); - if (listActualTypeArguments.length == 0) { - //如果没有数据 - return null; - } else if (listActualTypeArguments.length == 1) { - //如果只有一种类型 - String typeName = listActualTypeArguments[0].getTypeName(); - //如果此类型存在泛型,移除泛型 - typeName = typeName.replaceAll("<[\\w\\.\\, ]+>" , ""); - try { - return Class.forName(typeName); - } catch (ClassNotFoundException e) { - //将异常转化为运行时 - throw new RuntimeException(e); - } - } else { - //如果多个类型,直接返回Object类型 - return Object.class; - } - } - - /** - * 获取数组的组件类型 - * @param trr - * @param - * @return - */ - public static Class getArrayGeneric(T[] trr){ - //获取组件类型 - return trr.getClass().getComponentType(); - } - - /** - * 获取数组的组件类型 - * @param - * @return - */ - public static Class getArrayGeneric(Class tClass){ - return tClass.getComponentType(); - } - - - /** - * 获取一个list字段的泛型类型
- * 这个字段必须是一个list类型的字段! - * @param c - * @param fieldName - * @return - * @throws ClassNotFoundException - */ - public static Class getListFieldGeneric(Class c , String fieldName) { - return getListFieldGeneric(fieldGetter(c , fieldName)); - } - - /** - * 获取一个list字段的泛型类型
- * 这个字段必须是一个list类型的字段! - * @param obj - * @param fieldName - * @return - * @throws ClassNotFoundException - */ - public static Class getListFieldGeneric(Object obj , String fieldName) { - return getListFieldGeneric(obj.getClass() , fieldName); - } - - - - /** - * 判断一个Class对象是否为另一个对象的实现类 - * - * @param child 进行寻找的子类 - * @param findFather 被寻找的父类 - * @return - */ - public static boolean isChild(Class child, Class findFather) { - //如果自身就是这个类,直接返回true - if (child.equals(findFather)) { - return true; - } - - /* - 两个方向,一个是向父继承类递归,一个是向接口递归 - */ - //子类继承的父类 - Class superClass = child.getSuperclass(); - //子类实现的接口 - Class[] interfaces = child.getInterfaces(); - //如果全部为null,直接返回false - if (superClass == null && interfaces.length == 0) { - return false; - } - //进行判断-先对当前存在的两类型进行判断 - if (superClass != null && superClass.equals(findFather)) { - //如果发现了,返回true - return true; - } - - //遍历接口并判断 - for (Class interClass : interfaces) { - if (interClass.equals(findFather)) { - return true; - } - } - - //如果当前的没有发现,递归查询 - //如果没有发现,递归父类寻找 - if (superClass != null && isChild(superClass, findFather)) { - return true; - } - - //如果父类递归没有找到,进行接口递归查询 - //遍历 - for (Class interClass : interfaces) { - if (isChild(interClass, findFather)) { - return true; - } - } - - //未查询到 - return false; - } - - /** - * 判断一个Class对象是否为另一个对象的实现类 - * - * @param child 进行寻找的子类的实现类 - * @param findFather 被寻找的父类 - * @return - */ - public static boolean isChild(Object child, Class findFather) { - return isChild(child.getClass(), findFather); - } - - - - /** - * 单词开头大写 - * - * @param str - * @return - * @author ForteScarlet - */ - public static String headUpper(String str) { - return Character.toUpperCase(str.charAt(0)) + str.substring(1); - } - - /** - * 获取类名 - * - * @param c - * @return - * @author ForteScarlet - */ - public static String getClassName(Class c) { - String name = c.getName(); - String[] split = name.split("\\."); - return split[split.length - 1]; - } - - /** - * 通过对象获取类名 - * - * @param o - * @return - * @author ForteScarlet - */ - public static String getClassName(Object o) { - return getClassName(o.getClass()); - } - - - /** - * 只要传入的参数中任意一个出现了null则会抛出空指针异常 - * @param all - */ - public static void allNonNull(Object... all){ - for(Object o : all){ - if(o == null){ - throw new NullPointerException(); - } - } - } - - - - /* —————————————————————————————————————— 缓存字段接口 ———————————————————————————————————— */ - - /** - * 缓存字段的接口,定义获取一个缓存字段的值的方法 - * @param - * 字段所属的类型 - */ - private static interface CacheField{ - /** - * 获取一个缓存字段的值 - * @param object - *用于获取字段值的实例 - * @return - */ - InvokeResult fieldValue(T object); - - /** - * 为缓存字段的值赋值 - * @param object - * @param param - * @return - */ - InvokeResult fieldValueSet(T object, Object param); - - /** - * 获取Getter方法 - * @return - */ - Method getGetter(); - - /** - * 获取Setter方法 - * @return - */ - Method getSetter(); - - /** - * 获取字段对象 - * @return - */ - Field getField(); - - } - - /* —————————————————————————————————————— 单缓存字段相关方法 *基本全部为本类内部使用* ———————————————————————————————————— */ - - - - /** - * 向缓存中增加一个字段记录并返回这个新的缓存字段 - * @param field - * @param fieldWhereClass - * @param getter - * @param setter - */ - private static SingleCacheField saveSingleCacheField(Class fieldWhereClass , Field field, Method getter , Method setter){ - if(field.getName().split("\\.").length > 1){ - throw new RuntimeException("字段["+ field +"]并非单层字段"); - } - //先查看是否有这个字段 - SingleCacheField singleCacheField = (SingleCacheField)getCacheField(fieldWhereClass, field.getName()); - if(singleCacheField != null){ - //如果已经有这个缓存了,查看getter和setter是否存在 - //准备好Cache,有可能会进行更新操作 - SingleCacheField cache; - Method cGetter = singleCacheField.getGetter(); - Method cSetter = singleCacheField.getSetter(); - //判断是否更新 - boolean isUpdate = false; - - //判断getter - if(cGetter == null && getter != null){ - //getter为空,且传入的getter不为空 - isUpdate = true; - cGetter = getter; - } - - //判断setter - if(cSetter == null && setter != null){ - //setter为空,且传入的setter不为空 - //变更状态,设置getter - isUpdate = true; - cSetter = setter; - } - - //判断是否更新 - if(isUpdate){ - cache = new SingleCacheField(fieldWhereClass, field, cGetter, cSetter); - updateSingleCacheField(cache); - return cache; - } - //如果不需要更新,直接返回获取值 - return singleCacheField; - - }else{ - //不存在,直接返回 - SingleCacheField newSingleCacheField = new SingleCacheField<>(fieldWhereClass, field, getter, setter); - updateSingleCacheField(newSingleCacheField); - return newSingleCacheField; - } - } - - /** - * 向缓存中增加一个字段记录并返回这个新的缓存字段 - * getter、setter均为null - * @param fieldWhereClass - * @param field - * @param - * @return - */ - private static SingleCacheField saveSingleCacheField(Class fieldWhereClass , Field field){ - return saveSingleCacheField(fieldWhereClass , field , null , null); - } - - /** - * 向缓存中增加一个字段记录 - * 不可使用多层级字段获取 - * @param fieldWhereClass - * @param fieldName - * @param getter - * @param setter - */ - private static SingleCacheField saveSingleCacheField(Class fieldWhereClass , String fieldName , Method getter , Method setter){ - return saveSingleCacheField(fieldWhereClass , getField(fieldWhereClass ,fieldName) , getter , setter); - } - - /** - * 向缓存中增加一个字段记录 - * 不可使用多层级字段获取 - * @param fieldWhereClass - * @param fieldName - * @param - * @return - */ - private static SingleCacheField saveSingleCacheField(Class fieldWhereClass , String fieldName){ - return saveSingleCacheField(fieldWhereClass , getField(fieldWhereClass ,fieldName)); - } - - - - - /** - * 储存一个getter方法 - * @param fieldWhereClass - * @param fieldName - * @param getter - * @param - */ - private static SingleCacheField saveSingleCacheFieldGetter(Class fieldWhereClass , String fieldName , Method getter){ - return saveSingleCacheField(fieldWhereClass , fieldName , getter , null); - } - - /** - * 储存一个getter方法 - * @param fieldWhereClass - * @param field - * @param getter - * @param - */ - private static SingleCacheField saveSingleCacheFieldGetter(Class fieldWhereClass , Field field , Method getter){ - return saveSingleCacheField(fieldWhereClass , field , getter , null); - } - - /** - * 储存一个setter方法 - * @param fieldWhereClass - * @param fieldName - * @param setter - * @param - */ - private static SingleCacheField saveSingleCacheFieldSetter(Class fieldWhereClass , String fieldName , Method setter){ - return saveSingleCacheField(fieldWhereClass , fieldName , null , setter); - } - - /** - * 储存一个setter方法 - * @param fieldWhereClass - * @param field - * @param setter - * @param - */ - private static SingleCacheField saveSingleCacheFieldSetter(Class fieldWhereClass , Field field , Method setter){ - return saveSingleCacheField(fieldWhereClass , field , null , setter); - } - - /** - * 更新一个或新增加一个字段缓存 - * @param newSingleCacheField - */ - private static void updateSingleCacheField(SingleCacheField newSingleCacheField){ - //字段所在类的Class对象 - Class fieldWhereClassIn = newSingleCacheField.getFieldWhereClassIn(); - //从缓存中获取整个Map集合 - HashMap cacheFields = SINGLE_FIELD_CACHE_MAP.get(fieldWhereClassIn); - if(cacheFields == null){ - //如果没有此类的相关记录 - //获取这个类的字段总数量 - int length = fieldWhereClassIn.getDeclaredFields().length; - HashMap hashMap = new HashMap<>(length); - //保存这个增加字段并添加至缓存 - hashMap.put(newSingleCacheField.getFieldName() , newSingleCacheField); - SINGLE_FIELD_CACHE_MAP.put(fieldWhereClassIn , hashMap); - }else{ - //有此类相关记录,保存或覆盖此字段信息 - cacheFields.put(newSingleCacheField.getFieldName() , newSingleCacheField); - } - } - - - /** - * 获取缓存中的字段的getter方法 - * @param fieldWhereClass - * @param fieldName - * @return - */ - private static Method getCacheFieldGetter(Class fieldWhereClass , String fieldName){ - //如果缓存中存在此字段,返回getter,否则返回null - return Optional.ofNullable(getCacheField(fieldWhereClass , fieldName)).map(CacheField::getGetter).orElse(null); - } - - /** - * 获取缓存中字段的setter方法 - * @param fieldWhereClass - * @param fieldName - * @return - */ - private static Method getCacheFieldSetter(Class fieldWhereClass , String fieldName){ - //如果缓存中存在此字段,返回getter,否则返回null - return Optional.ofNullable(getCacheField(fieldWhereClass , fieldName)).map(CacheField::getSetter).orElse(null); - } - - /* ———————————————————————————————————————— 单缓存字段内部类 ———————————————————————————————————— */ - - /** - * 单层字段缓存对象 - * 内部类,实现字段缓存,优化此工具类的效率 - * 字段的缓存,其中储存所在类的Class对象、字段名称、字段对象、字段类型、getter、setter - * *虽然为公共权限,但仅仅为了使其内部类可被外部访问而设* - */ - private static class SingleCacheField implements CacheField { - // 储存所在类的Class对象、字段名称、字段对象、字段类型、getter、setter - - /** 字段所在Class,不可变更 */ - private final Class FIELD_WHERE_CLASS; - - /** 字段名称 */ - private final String FIELD_NAME; - - /** 字段对象 */ - private final Field FIELD; - - /** 字段类型 */ - private final Class FIELD_TYPE; - - /** getter方法 */ - private final Method GETTER; - - /** setter方法 */ - private final Method SETTER; - - /* —————— 各种api —————— */ - - /** - * 通过实例对象获取字段值,返回一个封装类 - * success为是否成功的执行了 - * invoke代表执行的值 - * 如果执行失败,则invoke的值必然为null - * @param obj - * @return - */ - private InvokeResult objectGetter(Object obj){ - if(GETTER != null){ - try { - //执行getter方法 - Object invoke = GETTER.invoke(obj); - return InvokeResult.success(invoke); - } catch (Exception e) { - return InvokeResult.fail(); - } - }else{ - return InvokeResult.fail(); - } - } - - /** - * 通过一个实例对象设置字段值,返回一个封装类 - * setter没有返回值,则invoke必然为null - * 如果success为false,则说明方法执行出现错误或setter不存在 - * @param obj - * @param value - * @return - */ - private InvokeResult objectSetter(Object obj, Object value){ - if(SETTER != null){ - try { - MethodUtil.invoke(obj, new Object[]{value}, SETTER); - return InvokeResult.emptySuccess(); - } catch (InvocationTargetException | IllegalAccessException e) { - return InvokeResult.fail(); - } - }else{ - return InvokeResult.fail(); - } - } - - /** - * 获取字段所在类的Class对象 - * @return - */ - private Class getFieldWhereClassIn(){ - return this.FIELD_WHERE_CLASS; - } - - /** - * 获取字段名 - * @return - */ - private String getFieldName(){ - return FIELD_NAME; - } - - /** - * 获取字段 - * @return - */ - @Override - public Field getField(){ - return FIELD; - } - - /** - * 获取字段类型 - * @return - */ - private Class getFieldType(){ - return FIELD_TYPE; - } - - /** - * 获取getter方法 - * @return - */ - @Override - public Method getGetter(){ - return GETTER; - } - - /** - * 获取setter方法 - * @return - */ - @Override - public Method getSetter(){ - return SETTER; - } - - - /* - 重写equals方法和hashCode方法,使得字段名和所在Class类为区别本类的字段 - */ - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - SingleCacheField that = (SingleCacheField) o; - return FIELD_WHERE_CLASS.equals(that.FIELD_WHERE_CLASS) && - FIELD_NAME.equals(that.FIELD_NAME); - } - - @Override - public int hashCode() { - return Objects.hash(FIELD_WHERE_CLASS, FIELD_NAME); - } - - /** 构造-通过字段为字段名赋值 */ - private SingleCacheField(Class fieldWhereClass , Field field , Method getter , Method setter){ - //设置所属类 - this.FIELD_WHERE_CLASS = fieldWhereClass; - //设置字段相关 - this.FIELD = field; - this.FIELD_NAME = field.getName(); - this.FIELD_TYPE = field.getType(); - //获取此字段的getter方法 - this.GETTER = getter; - this.SETTER = setter; - } - - /** - * 获取字段的实例值 - * @param object - * @return - */ - @Override - public InvokeResult fieldValue(Object object) { - return objectGetter(object); - } - - /** - * 为字段赋值 - * @param object - * @param param - * @return - */ - @Override - public InvokeResult fieldValueSet(T object, Object param) { - //赋值 - try { - MethodUtil.invoke(object , new Object[]{param} , SETTER); - //如果没有出现异常,则说明方法执行成功,返回成功信息 - return InvokeResult.emptySuccess(); - } catch (InvocationTargetException | IllegalAccessException e) { - //如果出现异常,则说明方法执行错误,返回错误信息 - return InvokeResult.fail(); - } - } - - } - - - - - /* —————————————————————————————————————— 多层缓存对象相关方法 —————————————————————————————————————————— */ - - /** - * 尝试查询上层层级字段 - * @param thisLevelCacheField - * @param - * @param - * @return - */ - private static LevelCacheField findUpperLevelCacheField(LevelCacheField thisLevelCacheField){ - HashMap levelCacheFieldHashMap = LEVEL_FIELD_CACHE_MAP.get(thisLevelCacheField.getRootClass()); - try{ - LevelCacheField tryFoundUpper = levelCacheFieldHashMap.entrySet().parallelStream().filter(e -> (e.getValue().getLevel() + 1) == thisLevelCacheField.getLevel()).findFirst().map(Map.Entry::getValue).orElse(null); - return Optional.ofNullable(tryFoundUpper).orElse(null); - }catch (Exception ignore){ - //如果出现异常则说明没有查询到,不做处理,直接返回null - return null; - } - } - - /** - * 储存或覆盖一个多层级字段对象 - * 可选:上层字段、下层字段 - * 必要:根类、字段名、本类字段 - * @param rootClass - * 必要 根类 - * @param fieldName - * 必要 字段名 - * @param upper - * 可选 上层 - * @param lower - * 可选 下层 - * @param thisCacheField - * 必要 本类字段 - * @param - * 根类类型 - * @param - * 本类类型 - * @return - * 保存或更新的多层级对象 - */ - private static LevelCacheField saveLevelCacheField( Class rootClass , - String fieldName , - LevelCacheField upper , - LevelCacheField lower , - SingleCacheField thisCacheField){ - - - //通过根类获取 - HashMap levelCacheFieldHashMap = LEVEL_FIELD_CACHE_MAP.get(rootClass); - //判断有没有此根类的多级字段集 - if(levelCacheFieldHashMap != null){ - //有多层级字段集,根据字段名获取对象 - LevelCacheField levelCacheField = levelCacheFieldHashMap.get(fieldName); - - if(levelCacheField == null){ - //没有此多层级对象,创建并添加 - levelCacheField = new LevelCacheField<>(rootClass, fieldName, upper, lower, thisCacheField); - levelCacheFieldHashMap.put(fieldName , levelCacheField); - } - - //判断upper - if(levelCacheField.getUpperLevelField() == null){ - //如果原本没有上层 - //如果upper不为null,赋值 - if(upper != null){ - levelCacheField.setUpperLevelField(upper); - }else{ - //如果为null,则尝试从内存中寻找上层字段 - 根据level查找即可 - //如果有上层字段,则肯定同属一个根类,且上层level+1为此层level,此层level使用字段名切割判断 - LevelCacheField upperLevelCacheField = findUpperLevelCacheField(levelCacheField); - LevelCacheField tryFoundUpper = levelCacheFieldHashMap.entrySet().parallelStream().filter(e -> (e.getValue().getLevel() + 1) == fieldName.split("\\.").length).findFirst().map(Map.Entry::getValue).orElse(null); - //如果查询到了则赋值 - if(tryFoundUpper != null){ - levelCacheField.setUpperLevelField(tryFoundUpper); - } - } - } - - //判断lower - if(levelCacheField.getLowerLevelField() == null){ - - //如果lower不为null,赋值 - if(lower != null){ - levelCacheField.setLowerLevelField(lower); - }else{ - //如果lower为null,尝试从缓存中查找下层字段 - 根据level查找 - //如果有下层字段,则肯定同属一个根类,且下层level-1为此层level,此层level使用字段名切割判断 - try{ - LevelCacheField tryFoundLower = levelCacheFieldHashMap.entrySet().parallelStream().filter(e -> (e.getValue().getLevel() - 1) == fieldName.split("\\.").length).findFirst().map(Map.Entry::getValue).orElse(null); - levelCacheField.setLowerLevelField(tryFoundLower); - }catch (Exception ignore){ - //如果出现异常则说明没有查询到,不做处理 - } - } - } - - - //返回 - return levelCacheField; - - }else{ - //没有字段集,创建一个新的并保存 - HashMap newLevelCacheFieldHashMap = new HashMap<>(5); - //新的多层级缓存字段 - LevelCacheField newLevelCacheField = new LevelCacheField<>(rootClass, fieldName, null, null, thisCacheField); - //保存 - newLevelCacheFieldHashMap.put(fieldName, newLevelCacheField); - //根据根类记入缓存 - LEVEL_FIELD_CACHE_MAP.put(rootClass , newLevelCacheFieldHashMap); - - //返回 - return newLevelCacheField; - } - } - - /** - * 储存或覆盖一个多层级字段对象 - * 可选的上层字段、下层字段为null - * 必要:根类、字段名、本类字段 - * @param rootClass - * @param fieldName - * @param thisCacheField - * @param - * @param - * @return - */ - private static LevelCacheField saveLevelCacheField( Class rootClass , - String fieldName , - SingleCacheField thisCacheField){ - return saveLevelCacheField(rootClass, fieldName, null , null , thisCacheField); - } - - /** - * 储存或覆盖一个多层级字段对象的upper - * @param rootClass - * @param fieldName - * @param upper - * @param thisCacheField - * @param - * @param - * @return - */ - private static LevelCacheField saveLevelCacheFieldUpper( Class rootClass , - String fieldName , - LevelCacheField upper , - SingleCacheField thisCacheField){ - return saveLevelCacheField(rootClass, fieldName, upper , null , thisCacheField); - } - - /** - * 储存或覆盖一个多层级字段对象的lower - * @param rootClass - * @param fieldName - * @param lower - * @param thisCacheField - * @param - * @param - * @return - */ - private static LevelCacheField saveLevelCacheFieldLower( Class rootClass , - String fieldName , - LevelCacheField lower , - SingleCacheField thisCacheField){ - return saveLevelCacheField(rootClass, fieldName, null , lower , thisCacheField); - } - - - /* —————————————————————————————————————— 多层缓存对象内部类 —————————————————————————————————————————— */ - - /** - * 多层级字段缓存对象 - * 内部类,实现字段缓存,优化此工具类的效率 - * **由于多层级字段的缓存与获取很容易发生错误和异常,所以尽可能的将异常处理,提高容错性 - * @param 多层级缓存字段的根类类型 - * @param 多层级缓存字段的当前类类型 - */ - private static class LevelCacheField implements CacheField { - /* - 多层级,就要一环套一环 - 每层概念上都会有:上层、下层、当前层 - 当前层即为一个SingleCacheField对象 - - */ - - /** 多层级的根层所在类 */ - private final Class ROOT_CLASS; - - /** 字段名,唯一且不可变 */ - private final String FIELD_NAME; - - /** 上层对象 */ - private LevelCacheField upperLevelField; - - /** 下层 */ - private LevelCacheField lowerLevelField; - - /** 当前层 */ - private SingleCacheField thisLevelField; - - private final int LEVEL; - - /* —————————— 相关api —————————— */ - - /** - * 当前层所在类 - * @return - */ - public Class thisLevelClass(){ - return thisLevelField.getFieldWhereClassIn(); - } - - @Override - public Method getGetter() { - return thisLevelField.getGetter(); - } - - @Override - public Method getSetter() { - return thisLevelField.getSetter(); - } - - @Override - public Field getField() { - return thisLevelField.getField(); - } - - - /* —————————— getter setter —————————— */ - - /** - * 当前字段在根类中的层级数,1级为根字段,根据字段名的切割计算 - * @return - */ - public int getLevel(){ - return this.LEVEL; - } - - public Class getRootClass(){ - return ROOT_CLASS; - } - - public String getFieldName(){ - return FIELD_NAME; - } - - public LevelCacheField getUpperLevelField() { - return upperLevelField; - } - - /** - * 设置upper的同时设置对方的lower - * @param upperLevelField - */ - public void setUpperLevelField(LevelCacheField upperLevelField) { - if(this.upperLevelField != null){ - this.upperLevelField = upperLevelField; - //直接赋值,防止无限循环 - upperLevelField.lowerLevelField = this; - } - } - - public LevelCacheField getLowerLevelField() { - return lowerLevelField; - } - - /** - * 设置lower的同时设置对方的upper - * @param lowerLevelField - */ - public void setLowerLevelField(LevelCacheField lowerLevelField) { - if(lowerLevelField != null){ - this.lowerLevelField = lowerLevelField; - //直接赋值,防止无限循环 - lowerLevelField.upperLevelField = this; - } - } - - public SingleCacheField getThisLevelField() { - return thisLevelField; - } - - public void setThisLevelField(SingleCacheField thisLevelField) { - this.thisLevelField = thisLevelField; - } - - /* —————— toString、equals、hashcode —————— */ - - @Override - public String toString() { - return "LevelCacheField{" + - "rootClass=" + ROOT_CLASS + - ", fieldName='" + FIELD_NAME + '\'' + - ", thisLevelFieldClass=" + thisLevelField.getFieldWhereClassIn() + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - LevelCacheField that = (LevelCacheField) o; - return ROOT_CLASS.equals(that.ROOT_CLASS) && - FIELD_NAME.equals(that.FIELD_NAME); - } - - @Override - public int hashCode() { - return Objects.hash(ROOT_CLASS, FIELD_NAME); - } - - /* —————— 根类匹配方法 —————— */ - - /** - * 如果根类不匹配则抛出异常 - * @param myRoot - * @param inRoot - */ - private static void isSameRoot(Class myRoot , Class inRoot){ - if(!myRoot.equals(inRoot)){ - throw new NotSameRootException(myRoot , inRoot); - } - - } - - /** 构造 */ - public LevelCacheField(Class rootClass , String fieldName, LevelCacheField upperLevelField, LevelCacheField lowerLevelField, SingleCacheField thisLevelField){ - //验证必要参数 - allNonNull(rootClass , fieldName , thisLevelField); - - //根层Class - this.ROOT_CLASS = rootClass; - - //为字段名赋值,不可为null - this.FIELD_NAME = fieldName; - - //为层级赋值 - 根据字段名切割‘.’计算层级数 - this.LEVEL = fieldName.split("\\.").length; - - //上层对象,可为null - //如果不为null,则根层类必须相同 - if(upperLevelField != null){ - isSameRoot(rootClass , upperLevelField.getRootClass()); - this.upperLevelField = upperLevelField; - }else{ - this.upperLevelField = null; - } - - //下层对象,可为null - //如果不为null,则根层类必须相同 - if(lowerLevelField != null){ - isSameRoot(rootClass , lowerLevelField.getRootClass()); - this.lowerLevelField = lowerLevelField; - }else{ - this.lowerLevelField = null; - } - - //当前层字段对象,不可为null - this.thisLevelField = thisLevelField; - - } - - /** - * 使用根类具体对象返回当前层级的当前字段的值 - * 从上层对象遍历至此,由远到近 - * @return - */ - private Object thisLevelFieldGetter(R r){ - //如果有上层对象 - if(upperLevelField != null){ - //如果有上层对象,则先获取上层对象的字段值,再根据上层对象的字段值返回对象获取当前字段值 - //上层字段值的获取对象的类型为根类类型 - //得到上层对象的值,使用上层对象获取本类对象 - Object upperInvoke = upperLevelField.thisLevelFieldGetter(r); - if(upperInvoke != null){ - try { - //使用上层字段的值执行getter - return getThisLevelField().getGetter().invoke(upperInvoke); - } catch (IllegalAccessException | InvocationTargetException e) { - // 出现异常,展示异常并返回一个null - e.printStackTrace(); - return null; - } - }else{ - //如果上层返回值为null,则直接返回null - return null; - } - }else{ - //如果没有上层对象 - //如果level不为1,则尝试查询上层,如果查询不到则返回null - if(LEVEL != 1){ - // 查询上层字段 - LevelCacheField upperLevelCacheField = findUpperLevelCacheField(this); - if(upperLevelCacheField != null){ - //如果查询到了,赋值并重新获取 - this.upperLevelField = upperLevelCacheField; - return thisLevelFieldGetter(r); - }else{ - //如果没有找到上层对象,返回null - return null; - } - }else{ - //如果level为1没有上层对象,认为当前即为根类,获取当前层字段值 - InvokeResult invokeResult = thisLevelField.objectGetter(r); - //抛出异常并不合适,这里选择不做处理,直接返回null - return invokeResult.getInvoke(); - } - } - } - - - /** - * 为字段赋值 - * @param object - * @param param - * @return - */ - private Boolean thisLevelFieldSetter(R object, Object param) { - //如果有上层字段, - if(upperLevelField != null){ - //如果有上层字段值,则先获取上层字段的字段值,再根据上层字段的值为当前字段赋值 - Object upperInvoke = upperLevelField.thisLevelFieldGetter(object); - //如果上层对象的获取值为null,尝试为上层字段赋一个新的实例对象 - if(upperInvoke == null){ - try { - //获取上层对象的SETTER方法和字段类型 - Method upperSetter = upperLevelField.getSetter(); - Object upperInstance = upperLevelField.getThisLevelField().getFieldType().newInstance(); - //为上层字段的上层字段赋值 - //获取上上层对象的实例 - InvokeResult upperUpperInvokeResult = upperLevelField.upperLevelField.fieldValue(object); - //如果获取失败或没有值,直接返回null - if(upperUpperInvokeResult.isSuccess() && upperUpperInvokeResult.getInvoke() != null){ - MethodUtil.invoke(upperUpperInvokeResult, new Object[]{upperInstance}, upperSetter); - //赋值之后重新获取 - return thisLevelFieldSetter(object , param); - }else{ - return false; - } - } catch (Exception e) { - e.printStackTrace(); - //若是出现异常,则说明上层对象无法赋值 - //没有上层对象则无法为本层对象赋值,直接返回false - return false; - } - }else{ - try { - //上层对象的获取值不为null,使用上层对象的返回值赋值 - Method setter = thisLevelField.getSetter(); - MethodUtil.invoke(object, new Object[]{param}, setter); - return true; - } catch (Exception e) { - //如果出现异常,则说明赋值出现错误,返回false - e.printStackTrace(); - return false; - } - } - }else{ - //如果没有上层对象,判断层级 - if(LEVEL != 1){ - //如果层级不为1,则尝试查询上层,如果查询不到则返回null - LevelCacheField upperLevelCacheField = findUpperLevelCacheField(this); - if(upperLevelCacheField != null){ - //如果查询到了,赋值并重新查询 - this.upperLevelField = upperLevelCacheField; - return thisLevelFieldSetter(object, param); - }else{ - //没有查询到,直接返回false - return false; - } - }else{ - //层级为1,则本类即为根类,直接赋值并返回赋值结果 - InvokeResult invokeResult = thisLevelField.objectSetter(object, param); - return invokeResult.isSuccess(); - } - } - } - - - /** - * 获取字段的实例 - * @param object - * @return - */ - @Override - public InvokeResult fieldValue(R object) { - Object o = thisLevelFieldGetter(object); - if(o != null){ - return InvokeResult.success(o); - }else{ - return InvokeResult.fail(); - } - } - - /** - * 为字段赋值并封装结果 - * @param r - * @param param - * @return - */ - @Override - public InvokeResult fieldValueSet(R r , Object param){ - Boolean isSuccess = thisLevelFieldSetter(r, param); - if(isSuccess){ - return InvokeResult.emptySuccess(); - }else{ - return InvokeResult.fail(); - } - } - - } - - - - - - /* ———————————————————————————————————— 缓存获取 封装类 —————————————————————————————————— */ - - /** - * 内部类 - * 方法执行的返回值封装类,此类除了重写方法以外的唯一公共接口 - */ - public static class InvokeResult{ - private final boolean success; - private final Object invoke; - private InvokeResult(boolean success , Object invoke){ - this.success = success; - this.invoke = invoke; - } - - /* ---- factory ----*/ - - static InvokeResult emptySuccess(){ - return new InvokeResult(true , null); - } - static InvokeResult success(Object invoke){ - return new InvokeResult(true , invoke); - } - static InvokeResult fail(){ - return new InvokeResult(false, null); - } - - /* ---- getter ---- */ - - public boolean isSuccess() { - return success; - } - public Object getInvoke() { - return invoke; - } - } - - /* ———————————————————————————————————— 缓存获取 方法 —————————————————————————————————— */ - - /** - * 从缓存中获取一个缓存字段 - * @param fieldWhereClass - * @return - */ - private static CacheField getCacheField(Class fieldWhereClass , String fieldName){ - //判断这是单层字段还是多层字段 - String[] split = fieldName.split("\\."); - if(split.length == 1){ - //是单层的 - HashMap singleCacheFieldHashMap = SINGLE_FIELD_CACHE_MAP.get(fieldWhereClass); - //如果有此字段的信息,返回获取值,如果没有直接返回null - SingleCacheField singleCacheField = Optional.ofNullable(singleCacheFieldHashMap).map(m -> m.get(fieldName)).orElse(null); - return singleCacheField; - }else{ - //如果长度不为1,则认为是多层对象 - HashMap levelCacheFieldHashMap = LEVEL_FIELD_CACHE_MAP.get(fieldWhereClass); - //如果有此字段的信息,返回获取值,如果没有直接返回null - LevelCacheField levelCacheField = Optional.ofNullable(levelCacheFieldHashMap).map(m -> m.get(fieldName)).orElse(null); - return levelCacheField; - } - } - - - - /* ———————————————————————————————————— 缓存异常 ———————————————————————————————————— */ - - /** - * 多层级对象根类不匹配异常 - */ - private static class NotSameRootException extends RuntimeException{ - NotSameRootException(Class myRoot , Class inRoot){ - super("多层级对象的根类不同!当前根类:["+ myRoot +"] 无法设置根类为["+ inRoot +"]的多层级对象!"); - } - } - - /** - * 多层级字段上层无返回值异常 - */ - private static class UpperLevelNoResultException extends RuntimeException{ - UpperLevelNoResultException(LevelCacheField upper){ - super("上层对象没有返回值:" + upper); - } - } - - - /** - * 构造私有化 - */ - private FieldUtils(){} - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/MethodUtil.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/MethodUtil.java deleted file mode 100644 index ee2e031..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/MethodUtil.java +++ /dev/null @@ -1,193 +0,0 @@ -package io.fluent.mocker.utils; - -import com.forte.util.MockConfiguration; -import com.forte.util.exception.ParameterSizeException; -import com.forte.util.invoker.ElementInvoker; -import com.forte.util.invoker.Invoker; -import com.forte.util.invoker.MethodInvoker; -import org.apache.commons.beanutils.ConvertUtils; - -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; -import javax.script.ScriptException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Parameter; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 方法执行工具 - * - * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - */ -public class MethodUtil { - - - /** - * 执行一个方法,可以为基本的数据类型进行转化 - * - * @param obj - * @param args - * @param method - * @return - * @throws InvocationTargetException - * @throws IllegalAccessException - */ - public static Object invoke(Object obj, Object[] args, Method method) throws InvocationTargetException, IllegalAccessException { - //获取参数的数据类型数组,准备转化数据类型 - Parameter[] parameters = method.getParameters(); - //如果传入参数与方法参数数量不符 ,抛出异常 - //不知道是否能识别 String... args 这种参数 - if (args.length != parameters.length) { - throw new ParameterSizeException(); - } - //创建一个新的Object数组保存转化后的参数,如果使用原数组的话会抛异常:ArrayStoreException - Object[] newArr = new Object[args.length]; - //遍历参数并转化 - for (int i = 0; i < parameters.length; i++) { - //使用BeanUtils的数据类型器对参数的数据类型进行转化 - //保存至新的参数集 - Class paramType = parameters[i].getType(); - Object arg = args[i]; - if(arg.getClass().equals(paramType)){ - newArr[i] = arg; - }else{ - newArr[i] = ConvertUtils.convert(arg, paramType); - } - } - - //返回方法的执行结果 - return method.invoke(obj, newArr); - } - - /** - * 执行一个方法,可以为基本的数据类型进行转化 - * - * @param obj - * @param args - * @param methodName 方法名 - * @return - * @throws NoSuchMethodException - */ - public static Object invoke(Object obj, Object[] args, String methodName) throws NoSuchMethodException { - //通过反射获取此方法 - Method[] methods = Arrays.stream(obj.getClass().getMethods()).filter(m -> m.getName().equals(methodName) && m.getParameters().length == args.length).toArray(Method[]::new); - for (Method m : methods) { - try { - return invoke(obj, args, m); - } catch (Exception e) { - e.printStackTrace(); - } - } - - throw new NoSuchMethodException(); - } - - - /** - * Filter out the Object Methods
- * 过滤掉Object中继承来的方法 - * @param methods 需要过滤的方法列表 - */ - public static List getOriginal(List methods){ - return methods.stream().parallel().filter(m -> Arrays.stream(Object.class.getMethods()).noneMatch(om -> om.equals(m))).collect(Collectors.toList()); - } - - - /** - * 将一个方法存至缓存 - */ - private void saveChcheMethod() { - //TODO 完成方法的缓存,缓存方法的获取方式:根据类:方法名获取、字段获取 - - } - - - //创建一个js脚本执行器 - private static ScriptEngineManager manager = new ScriptEngineManager(); - private static ScriptEngine se = manager.getEngineByName("js"); - - /** - * js中的eval函数,应该是只能进行简单的计算 - * 利用js脚本完成 - * - * @param str 需要进行eval执行的函数 - * @return 执行后的结果 - */ - public static Object eval(String str) throws ScriptException { - //脚本执行并返回结果 - if(MockConfiguration.isEnableJsScriptEngine()){ - return se.eval(str); - }else{ - // 未开启脚本执行,直接返回 - return str; - } - } - - /** - * js中的eval函数,应该是只能进行简单的计算 - * 利用js脚本完成 - * - * @param str 需要进行eval执行的函数 - * @return 执行后的结果 - */ - public static Object evalCache(String str) { - try { - return eval(str); - } catch (ScriptException ignore) { - return str; - } -// //脚本执行并返回结果 -// if(MockConfiguration.isEnableJsScriptEngine()){ -// try { -// return se.eval(str); -// } catch (ScriptException ignore) { -// return str; -// } -// }else{ -// // 未开启脚本执行,直接返回 -// return str; -// } - } - - /** - * 创建一个方法执行者 - * - * @return - */ - public static Invoker createMethodInvoker(Object obj, Object[] args, Method method) { - return MethodInvoker.getInstance(obj, args, method); - } - - /** - * 创建一个方法为空的方法执行者,代表没有方法,将会输出指定的字符串 - * - * @return - */ - public static Invoker createNullMethodInvoker(Object nullValue) { - return MethodInvoker.getInstance(nullValue); - } - - /** - * 创建一个数组元素获取执行者 - * @param arr - * @return - */ - public static Invoker createArrayElementInvoker(Object[] arr){ - return ElementInvoker.getInstance(arr); - } - - /** - * 创建一个集合元素获取执行者 - * @param list - * @return - */ - public static Invoker createListElementInvoker(List list){ - return ElementInvoker.getInstance(list); - } - -} - - diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/MockUtil.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/MockUtil.java deleted file mode 100644 index 535845f..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/MockUtil.java +++ /dev/null @@ -1,1100 +0,0 @@ -package io.fluent.mocker.utils; - -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Date; -import java.util.Random; - -/** - *

- * 随机数据助手,可能会用到的所有随机方法
- * 此类所有的方法,只要在方法名前加上'@' 即可在Mock中作为映射指令 - * 例如: - *

- * - *

map.put("name" , "@cname");

- *

map.put("age" , "@age");

- *

map.put("place" , "@ctitle(2,5)");

- *
- *

- *

- * - *

※以下列表仅供参考,一切以方法内实际参数为准,此注释有些情况可能未及时更新。

- * - *

--名称、title等相关

- *
    - *
  • - * {@link MockUtil#cname()}获取一个中文姓名 - *
  • - *
  • - * {@link MockUtil#cnames(Integer, Integer)}获取指定数量区间[min , max]个随机中文名 - *
  • - *
  • - * {@link MockUtil#cnames(Integer)}获取指定数量个随机中文名 - *
  • - *
  • - * {@link MockUtil#name()}获取一个英文姓名 - *
  • - *
  • - * {@link MockUtil#names(Integer, Integer)}获取指定数量区间[min, max]个随机英文姓名 - *
  • - *
  • - * {@link MockUtil#names(Integer)}获取指定数量num个随机英文姓名 - *
  • - *
  • - * {@link MockUtil#ctitle()}获取一段中文,3-5 - *
  • - *
  • - * {@link MockUtil#ctitle(Integer)}获取一段指定长度的中文 - *
  • - *
  • - * {@link MockUtil#ctitle(Integer)}获取指定数量区间个随机汉字,区间[min,max] - *
  • - *
  • - * {@link MockUtil#title()}获取一段指定长度的英文5-10 - *
  • - *
  • - * {@link MockUtil#title(Integer)}获取一段指定长度的英文 - *
  • - *
  • - * {@link MockUtil#title(Integer)}获取指定数量区间个随机英文,区间[min,max] - *
  • - *
  • - * {@link MockUtil#UUID()}获取一个UUID - *
  • - *
- * - *

--date相关

- *
    - *
  • - * {@link MockUtil#date()}获取随机日期 1990 - 现在 - *
  • - *
  • - * {@link MockUtil#toDateStr()}返回一个日随机日期的字符串 - *
  • - *
  • - * {@link MockUtil#time(String)}返回一个随机时间的字符串 - *
  • - *
  • - * {@link MockUtil#time()}返回一个随机时间的字符串,格式为HH:mm:ss - *
  • - *
  • - * {@link MockUtil#toDateTime(String)}返回一个随机时间日期的字符串 - *
  • - *
  • - * {@link MockUtil#toDateTime()}返回一个随机日期时间的字符串,格式为yyyy-dd-MM HH:mm:ss - *
  • - *
- * - *

--number相关

- *
    - *
  • - * {@link MockUtil#age()}获取一个随机年龄 12-80 - *
  • - *
  • - * {@link MockUtil#integer()}获取随机数字 0-9 - *
  • - *
  • - * {@link MockUtil#integer(Integer)}获取指定长度的随机数,※不可超过int最大上限 - *
  • - *
  • - * {@link MockUtil#integer(Integer, Integer)}获取指定区间[a,b]的随机数,※不可超过int最大上限 - *
  • - *
  • - * {@link MockUtil#doubles(Integer, Integer, Integer, Integer)}获取指定区间[a,b]的小数,指定小数位数[endL,endR],double类型 - *
  • - *
  • - * {@link MockUtil#doubles(Integer, Integer, Integer)}获取指定区间[a,b]的小数,指定小数位数[end],double类型 - *
  • - *
  • - * {@link MockUtil#doubles(Integer, Integer)}获取指定区间[a,b]的小数,默认小数位数为0,double类型 - *
  • - *
  • - * {@link MockUtil#doubles(Integer)}获取指定数值为a的小数,默认小数位数为0,double类型 - *
  • - *
  • - * {@link MockUtil#UUNUM()}获取一个32位的随机数字 - *
  • - *
  • - * {@link MockUtil#getNumber(Integer)}获取任意长度的随机整数 - *
  • - *
  • - * {@link MockUtil#getDouble(Integer, Integer)}获取指定位的小数 - *
  • - *
  • - * {@link MockUtil#getDouble(Integer, Integer, Integer, Integer)}获取指定位的小数 - *
  • - *
  • - * {@link MockUtil#UUDOUBLE()}获取32位小数,小数为2位 - *
  • - *
- *

--String character相关

- *
    - *
  • - * {@link MockUtil#bool()}返回一个随机布尔值 - *
  • - *
  • - * {@link MockUtil#bool(double)}根据概率返回布尔值 - *
  • - *
- * - *

--String character相关

- *
    - *
  • - * {@link MockUtil#character()}获取一个随机字符 - *
  • - *
  • - * {@link MockUtil#character(Character[]...)}在提供的字符字典(数组中)随机 返回 - *
  • - *
  • - * {@link MockUtil#word(Integer)}返回一个随机的假单词,指定长度区间[min,max] - *
  • - *
  • - * {@link MockUtil#word(Integer, Integer)}返回一个随机的假单词,指定长度 - *
  • - *
  • - * {@link MockUtil#word()}返回一个随机的假单词 - *
  • - *
  • - * {@link MockUtil#cword(Integer)}返回一个随机的假中文词语,指定长度区间[min,max] - *
  • - *
  • - * {@link MockUtil#cword(Integer)}返回一个随机的假中文词语,指定长度 - *
  • - *
  • - * {@link MockUtil#cword()}返回一个随机的假中文词语 - *
  • - *
- *

--color相关

- *
    - *
  • - * {@link MockUtil#color()}获取一个随机颜色的16进制代码 - *
  • - *
- *

--text相关

- *
    - *
  • - * {@link MockUtil#sentence(Integer, Integer)}随机假英文句子,句子中的单词数量为参数的区间[min,max] - *
  • - *
  • - * {@link MockUtil#sentence(Integer)}返回指定长度的句子 - *
  • - *
  • - * {@link MockUtil#sentence()}返回长度为12-18长度的句子 - *
  • - *
  • - * {@link MockUtil#csentence(Integer, Integer)}随机假中文句子,句子中的单词数量为参数的区间[min,max] - *
  • - *
  • - * {@link MockUtil#csentence(Integer)}返回指定长度的中文句子 - *
  • - *
  • - * {@link MockUtil#csentence()}返回长度为5-10长度的中文句子 - *
  • - *
  • - * {@link MockUtil#paragraph(Integer, Integer)}返回一个文本,文中句子数量为参数区间[min,max] - *
  • - *
  • - * {@link MockUtil#paragraph(Integer)}返回指定句子数量的文本 - *
  • - *
  • - * {@link MockUtil#paragraph()}返回一个有3-7个句子的文本 - *
  • - *
  • - * {@link MockUtil#cparagraph(Integer, Integer)}返回一个文本,文中句子数量为参数区间[min,max] - *
  • - *
  • - * {@link MockUtil#cparagraph(Integer)}返回指定句子数量的文本 - *
  • - *
  • - * {@link MockUtil#cparagraph()}返回一个有3-7个句子的文本 - *
  • - *
- *

--web相关

- *
    - *
  • - * {@link MockUtil#ip()}获取一个随机IP - *
  • - *
  • - * {@link MockUtil#tId()}获取一个随机的顶级域名 - *
  • - *
  • - * {@link MockUtil#email(String, String)}返回一个随机邮箱,可以指定邮箱的名称(@后面的名字)和顶级域名 - *
  • - *
  • - * {@link MockUtil#email(String)}返回一个随机邮箱,可以指定邮箱的名称(@后面的名字) - *
  • - *
  • - * {@link MockUtil#email()}返回一个随机邮箱 - *
  • - *
  • - * {@link MockUtil#domain(String)}随机生成一个域名,可指定顶级域名 - *
  • - *
  • - * {@link MockUtil#domain()}随机生成一个域名 - *
  • - *
  • - * {@link MockUtil#url(String)}随机一个url路径,可指定域名 - *
  • - *
  • - * {@link MockUtil#url()}随机一个url - *
  • - *
- * - * 注意:此类在进行方法重载的时候不应出现参数数量相同的重载方法 - * - * @author ForteScarlet - */ -@SuppressWarnings({"unused", "SpellCheckingInspection"}) -public class MockUtil { - - - /* —————————— 默认参数 ———————————— */ - /** - * {@link #date()}默认使用的格式化参数 - */ - private static final String DATE_FORMAT; - - private static final SimpleDateFormat SIMPLE_DATE_FORMAT; - - - /** - * {@link #time()}默认使用的格式化参数 - */ - private static final String TIME_FORMAT; - - private static final SimpleDateFormat SIMPLE_DATETIME_FORMAT; - - /** - * {@link #toDateTime()}默认使用的格式化参数 - */ - private static final String DATETIME_FORMAT; - - private static final SimpleDateFormat SIMPLE_TIME_FORMAT; - - /** - * 顶级域名合集 - */ - private static final String[] DOMAINS; - - - //静态代码块加载资源 - static { - // 加载定义域名合集 - String domainStr = "top,xyz,xin,vip,win,red,net,org,wang,gov,edu,mil,biz,name,info,mobi,pro,travel,club,museum,int,aero,post,rec,asia"; - DOMAINS = domainStr.split(","); - - // 日期格式化 - DATE_FORMAT = "yyyy-dd-MM"; - SIMPLE_DATE_FORMAT = new SimpleDateFormat(DATE_FORMAT); - - DATETIME_FORMAT = "yyyy-dd-MM HH:mm:ss"; - SIMPLE_DATETIME_FORMAT = new SimpleDateFormat(DATE_FORMAT); - - TIME_FORMAT = "HH:mm:ss"; - SIMPLE_TIME_FORMAT = new SimpleDateFormat(DATE_FORMAT); - - } - - - /* —————————— name/chinese/cname —————————— */ - - /** - * 获取一个随机中文名称 - */ - public static String cname() { - return ChineseUtil.getName(); - } - - - /** - * 获取指定数量区间[min , max]个随机中文名 - * - * @param min 最小数量 - * @param max 最大数量 - * @return - */ - public static String[] cnames(Integer min, Integer max) { - //获取随机数量 - int num = RandomUtil.getNumberWithRight(min, max); - String[] names = new String[num]; - //遍历并获取 - for (int i = 0; i < num; i++) { - names[i] = cname(); - } - //返回结果 - return names; - } - - /** - * 获取指定数量个随机中文名 - * - * @return - */ - public static String[] cnames(Integer num) { - return cnames(num, num); - } - - /** - * 随机获取一个中文姓氏 - 百家姓中获取 - */ - public static String cfirstName() { - return ChineseUtil.getFamilyName(); - } - - /** - * 获取一个随机英文姓名-两个开头大写的英文字母(title(2,7)+" "+title(2,7)) - */ - public static String name() { - int min = 2, max = 7; - return title(min, max) + " " + title(min, max); - } - - /** - * 获取指定数量区间[min, max]个随机英文姓名 - * - * @param min 最少数量 - * @param max 最大数量 - * @return - */ - public static String[] names(Integer min, Integer max) { - //获取随机数量 - int num = RandomUtil.getNumberWithRight(min, max); - String[] names = new String[num]; - //遍历并获取 - for (int i = 0; i < num; i++) { - names[i] = name(); - } - //返回结果 - return names; - } - - /** - * 获取指定数量num个随机英文姓名 - * - * @param num 获取数量 - * @return - */ - public static String[] names(Integer num) { - return names(num, num); - } - - /** - * 获取3-5个随机汉字 - */ - public static String ctitle() { - return ctitle(3, 5); - } - - - /** - * 获取指定数量个随机汉字 - * - * @param num - */ - public static String ctitle(Integer num) { - return ChineseUtil.getChinese(num); - } - - /** - * 获取指定数量区间个随机汉字,区间[min,max] - * - * @param min 最少数量 - * @param max 最大数量 - */ - public static String ctitle(Integer min, Integer max) { - return ChineseUtil.getChinese(RandomUtil.getNumberWithRight(min, max)); - } - - - /** - * 获取5-10长度的英文字符串,开头大写 - */ - public static String title() { - return title(5, 10); - } - - /** - * 获取指定长度的英文字符串,开头大写 - * - * @param num - */ - public static String title(Integer num) { - return title(num, num); - } - - /** - * 获取指定长度的英文字符串,开头大写 - * - * @param min 最小长度 - * @param max 最大长度 - */ - public static String title(Integer min, Integer max) { - int num = RandomUtil.getNumberWithRight(min, max); - String title = RandomUtil.getRandomString(num, false); - //全部小写,开头大写 - return FieldUtils.headUpper(title); - } - - /** - * 获取指定长度的英文字符串,纯小写 - * - * @param min 最小长度 - * @param max 最大长度 - */ - public static String string(Integer min, Integer max) { - return word(min, max); - } - - /** - * 获取指定长度的英文字符串,纯小写 - * - * @param num - */ - public static String string(Integer num) { - return string(num, num); - } - - /** - * 获取5-10长度的英文字符串,纯小写 - */ - public static String string() { - return string(5, 10); - } - - /** - * 获取指定长度的英文字符串,纯大写 - * - * @param min 最小长度 - * @param max 最大长度 - */ - public static String stringUpper(Integer min, Integer max) { - int num = RandomUtil.getNumberWithRight(min, max); - return RandomUtil.getRandomUpperString(num); - } - - /** - * 获取指定长度的英文字符串,纯大写 - * - * @param num - */ - public static String stringUpper(Integer num) { - return stringUpper(num, num); - } - /** - * 获取5-10长度的英文字符串,纯大写 - */ - public static String stringUpper() { - return stringUpper(5, 10); - } - - - - - /** - * 获取一个UUID - */ - public static String UUID() { - return RandomUtil.getUUID(); - } - - - - /* —————————— date —————————— */ - - /** - * 获取随机日期 - * 时间:1990 - 现在 - */ - public static Date date() { - Calendar calendar = Calendar.getInstance(); - //设置年份等参数 - int nowYear = calendar.get(Calendar.YEAR); - int nowDay = calendar.get(Calendar.DAY_OF_YEAR); - - //设置随机年份 - calendar.set(Calendar.YEAR, RandomUtil.getNumberWithRight(1990, nowYear)); - //设置随机日期 - calendar.set(Calendar.DAY_OF_YEAR, RandomUtil.getNumberWithRight(1, nowDay)); - //设置随机小时 - calendar.set(Calendar.HOUR_OF_DAY, RandomUtil.getNumberWithRight(1, 24)); - //设置随机分钟 - calendar.set(Calendar.MINUTE, RandomUtil.getNumberWithRight(1, 60)); - //设置随机秒 - calendar.set(Calendar.SECOND, RandomUtil.getNumberWithRight(1, 60)); - - //返回随机日期 - return calendar.getTime(); - } - - /** - * 返回一个随机日期的字符串 - * - * @param format - */ - public static String toDateStr(String format) { - return new SimpleDateFormat(format).format(date()); - } - - /** - * 返回一个随机日期的字符串,格式为yyyy-dd-MM - */ - public static String toDateStr() { - return SIMPLE_DATE_FORMAT.format(date()); - } - - /** - * 返回一个随机时间的字符串 - * - * @param format - */ - public static String time(String format) { - return new SimpleDateFormat(format).format(date()); - } - - /** - * 返回一个随机时间的字符串,格式为HH:mm:ss - */ - public static String time() { - return SIMPLE_TIME_FORMAT.format(date()); - } - - /** - * 返回一个随机时间日期的字符串 - * - * @param format - */ - public static String toDateTime(String format) { - return new SimpleDateFormat(format).format(date()); - } - - /** - * 返回一个随机日期时间的字符串,格式为yyyy-dd-MM HH:mm:ss - */ - public static String toDateTime() { - return SIMPLE_DATETIME_FORMAT.format(date()); - } - - /* —————————— number age —————————— */ - - /** - * 获取一个随机年龄 - * 12 - 80 - */ - public static Integer age() { - return RandomUtil.getNumberWithRight(12, 80); - } - - /** - * 获取随机数字 - * 0-9 - */ - public static Integer integer() { - return RandomUtil.getNumber(1); - } - - /** - * 获取指定长度的随机数 - * - * @param length 长度,长度请不要超过整数型上限。
如果需要获取无限长度的整数请使用{@link MockUtil#getNumber(Integer)} - */ - public static Integer integer(Integer length) { - return RandomUtil.getNumber(length); - } - - /** - * 获取指定区间[a,b]的随机数 - * - * @param a 最小值 - * @param b 最大值 - * @return - */ - public static Integer integer(Integer a, Integer b) { - return RandomUtil.getNumberWithRight(a, b); - } - - - /** - * 获取制定区间[a,b]的小数,指定小数位数[endL,endR],double类型 - * - * @param a 整数部分的最小值 - * @param b 整数部分的最大值 - * @param endL 小数部分位数最小值 - * @param endR 小数部分位数最大值 - * @return - */ - public static Double doubles(Integer a, Integer b, Integer endL, Integer endR) { - int integer = integer(a, b); - //获取小数位数值 - int end = RandomUtil.getNumberWithRight(endL, endR); - double dou = Double.parseDouble(RandomUtil.toFixed(RandomUtil.getRandom().nextDouble(), end)); - return integer + dou; - } - - /** - * 获取指定区间[a,b]的小数,指定小数位数[end],double类型 - * - * @param a - * @param b - * @param end - * @return - */ - public static Double doubles(Integer a, Integer b, Integer end) { - return doubles(a, b, end, end); - } - - /** - * 获取指定区间[a,b]的小数,默认小数位数为0,double类型 - * - * @param a - * @param b - * @return - */ - public static Double doubles(Integer a, Integer b) { - return doubles(a, b, 0, 0); - } - - /** - * 获取指定数值为a的小数,默认小数位数为0,double类型 - * - * @param a - * @return - */ - public static Double doubles(Integer a) { - return a * 1.0; - } - - - /** - * 获取一个32位的随机数字 - */ - public static String UUNUM() { - int length = 32; - StringBuilder sb = new StringBuilder(length); - for (int i = 0; i < length; i++) { - sb.append(integer()); - } - return sb.toString(); - } - - /** - * 获取任意长度的随机整数 - * - * @param length - */ - public static String getNumber(Integer length) { - return getNumber(length, length); - } - - /** - * 获取任意长度的随机整数 - * - * @param min 最小长度 - * @param max 最大长度 - */ - public static String getNumber(Integer min, Integer max) { - //获取长度 - int length = RandomUtil.getNumberWithRight(min, max); - StringBuilder sb = new StringBuilder(length); - for (int i = 0; i < length; i++) { - sb.append(integer()); - } - return sb.toString(); - } - - - /** - * 获取指定位的小数 - * - * @param intLength 整数部分的长度 - * @param douLength 保留小数位数 - */ - public static String getDouble(Integer intLength, Integer douLength) { - return getDouble(intLength, intLength, douLength, douLength); - } - - - /** - * 获取指定位的小数的最大区间 - * - * @param intMinLength 整数部分的长度最小值 - * @param intMaxLength 整数部分的长度最大值 - * @param douMinLength 保留小数位数最小值 - * @param douMaxLength 保留小数位数最大值 - */ - public static String getDouble(Integer intMinLength, Integer intMaxLength, Integer douMinLength, Integer douMaxLength) { - //先获取整数位 - return getNumber(intMinLength, intMaxLength) + - "." + - getNumber(douMinLength, douMaxLength); - } - - - /** - * 获取32位小数,小数为2位 - */ - public static String UUDOUBLE() { - return getDouble(32, 2); - } - - - - /* ——————————————————————String character code—————————————————————— */ - - /** - * 获取一个随机字符 - */ - public static Character character() { - return RandomUtil.getRandomChar(); - } - - /** - * 在提供的字典(数组中)随机 返回 - * - * @param dic - */ - public static Character character(Character[]... dic) { - //合并集合 - Character[] characters = Arrays.stream(dic).flatMap(Arrays::stream).toArray(Character[]::new); - return characters[RandomUtil.getNumber(characters.length)]; - } - - /** - * 返回一个随机的假单词 - */ - public static String word() { - return word(3, 12); - } - - /** - * 返回一个随机的假单词,指定长度 - * - * @param length 指定长度 - */ - public static String word(Integer length) { - return RandomUtil.getRandomString(length, false); - } - - /** - * 返回一个随机的假单词,指定长度区间[min,max] - * - * @param min 最小长度 - * @param max 最大长度 - */ - public static String word(Integer min, Integer max) { - int num = RandomUtil.getNumberWithRight(min, max); - return RandomUtil.getRandomString(num, false); - } - - /** - * 返回一个随机的假中文词语,指定长度区间[min,max] - * - * @param min 最小长度 - * @param max 最大长度 - */ - public static String cword(Integer min, Integer max) { - return ctitle(min, max); - } - - /** - * 返回一个随机的假中文词语,指定长度 - * - * @param length 单词长度 - */ - public static String cword(Integer length) { - return ctitle(length); - } - - /** - * 返回一个随机的假中文词语,长度2-4 - */ - public static String cword() { - return ctitle(2, 4); - } - - - /* —————————————————————— color —————————————————————— */ - - /** - * 获取一个随机颜色的16进制代码 - */ - public static String color() { - return RandomUtil.randomColor$hexString(); - } - - /* —————————————————————— boolean —————————————————————— */ - - /** - * 返回一个随机布尔值 - */ - public static Boolean bool() { - return RandomUtil.getRandom().nextBoolean(); - } - - /** - * 根据概率返回布尔值 - * - * @param prob 返回true的概率,建议取值区间:0-1 - */ - public static Boolean bool(double prob) { - return RandomUtil.getProbability(prob); - } - - /* —————————————————————— text —————————————————————— */ - - /** - * 随机假英文句子,句子中的单词数量为参数的区间[min,max] - * - * @param min 单词最少数量 - * @param max 单词最多数量 - */ - public static String sentence(Integer min, Integer max) { - int num = RandomUtil.getNumberWithRight(min, max); - StringBuilder sb = new StringBuilder(num); - for (int i = 1; i <= num; i++) { - //首句子字母大写 - sb.append(i == 0 ? FieldUtils.headUpper(word()) : word()); - if (i != num) { - sb.append(' '); - } else { - //30%概率为!结尾 - if (RandomUtil.getProbability(0.3)) { - sb.append("! "); - //否则30%概率?结尾 - } else if (RandomUtil.getProbability(0.3)) { - sb.append("? "); - //否则。结尾 - } else { - sb.append(". "); - } - } - } - return sb.toString(); - } - - /** - * 返回指定长度的句子 - * - * @param length - */ - public static String sentence(Integer length) { - return sentence(length, length); - } - - /** - * 返回长度为12-18长度的句子 - */ - public static String sentence() { - return sentence(12, 18); - } - - /** - * 随机假中文句子,句子中的单词数量为参数的区间[min,max] - * - * @param min 单词最少数量 - * @param max 单词最多数量 - */ - public static String csentence(Integer min, Integer max) { - StringBuilder sb = new StringBuilder(); - int num = RandomUtil.getNumberWithRight(min, max); - for (int i = 1; i <= num; i++) { - //首句子字母大写 - sb.append(cword()); - if (i == num) { - //30%概率为!结尾 - if (RandomUtil.getProbability(0.3)) { - sb.append("!"); - //否则30%概率?结尾 - } else if (RandomUtil.getProbability(0.3)) { - sb.append("?"); - //否则。结尾 - } else { - sb.append("。"); - } - } - } - return sb.toString(); - } - - - /** - * 返回指定长度的中文句子 - * - * @param length - */ - public static String csentence(Integer length) { - return csentence(length, length); - } - - /** - * 返回长度为5-10长度的中文句子 - */ - public static String csentence() { - return csentence(5, 10); - } - - /** - * 返回一个文本,文中句子数量为参数区间[min,max] - * - * @param min - * @param max - */ - public static String paragraph(Integer min, Integer max) { - int num = RandomUtil.getNumberWithRight(min, max); - StringBuilder sb = new StringBuilder(num); - for (int i = 1; i <= num; i++) { - sb.append(sentence()); - } - return sb.toString(); - } - - /** - * 返回指定句子数量的文本 - * - * @param length - */ - public static String paragraph(Integer length) { - return paragraph(length, length); - } - - /** - * 返回一个有3-7个句子的文本 - */ - public static String paragraph() { - return paragraph(3, 7); - } - - /** - * 返回一个文本,文中句子数量为参数区间[min,max] - * - * @param min 最小数量 - * @param max 最大数量 - */ - public static String cparagraph(Integer min, Integer max) { - int num = RandomUtil.getNumberWithRight(min, max); - StringBuilder sb = new StringBuilder(num); - for (int i = 1; i <= num; i++) { - sb.append(csentence()); - } - return sb.toString(); - } - - /** - * 返回指定句子数量的文本 - * - * @param length - */ - public static String cparagraph(Integer length) { - return cparagraph(length, length); - } - - /** - * 返回一个有3-7个句子的文本 - */ - public static String cparagraph() { - return cparagraph(3, 7); - } - - - /* —————————————————————— web —————————————————————— */ - - /** - * 获取一个随机IP - */ - public static String ip() { - Random random = RandomUtil.getRandom(); - return (random.nextInt(255) + 1) + - "." + - (random.nextInt(255) + 1) + - '.' + - (random.nextInt(255) + 1) + - '.' + - (random.nextInt(255) + 1); - } - - /** - * 获取一个随机的顶级域名 - */ - public static String tId() { - return RandomUtil.getRandomElement(DOMAINS); - } - - /** - * 返回一个随机邮箱,可以指定邮箱的名称(@后面的名字)和顶级域名 - */ - public static String email(String emailName, String tid) { - - return word() + - '@' + - emailName + - '.' + - tid; - } - - /** - * 返回一个随机邮箱,可以指定邮箱的名称(@后面的名字) - */ - public static String email(String emailName) { - return email(emailName, tId()); - } - - /** - * 返回一个随机邮箱 - */ - public static String email() { - return email(word(), tId()); - } - - /** - * 随机生成一个域名,可指定顶级域名 - * - * @param tid 指定顶级域名 - */ - public static String domain(String tid) { - if (RandomUtil.getRandom().nextBoolean()) { - return "www." + word() + "." + tid; - } - return word() + '.' + tid; - } - - /** - * 随机生成一个域名 - */ - public static String domain() { - return domain(tId()); - } - - /** - * 随机一个url路径,可指定域名 - * - * @param domainName 指定域名 - */ - public static String url(String domainName) { - StringBuilder sb = new StringBuilder(32); - //url前半部分 - sb.append("http://").append(domainName).append('/').append(word()); - //每次有0.2的概率再追加一层路径 - while (RandomUtil.getProbability(0.2)) { - sb.append('/').append(word()); - } - return sb.toString(); - } - - /** - * 随机一个url - */ - public static String url() { - return url(domain()); - } - - - /* —————————————————————— 构造 —————————————————————— */ - - /** - * 构造私有化 - */ - private MockUtil() { } - - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/ProxyUtils.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/ProxyUtils.java deleted file mode 100644 index 503007e..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/ProxyUtils.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.fluent.mocker.utils; - -import com.forte.util.function.ExProxyHandler; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.Proxy; - -/** - * 动态代理工具类,为一个接口类型创建动态代理对象 - * @author ForteScarlet - */ -public class ProxyUtils { - - /** - * 为一个接口类型创建动态代理对象。 - * @param type 接口的类型 - * @param proxyHandler 动态代理的逻辑处理类 - * @param - * @return - */ - public static T proxy(Class type, ExProxyHandler proxyHandler){ - if (!Modifier.isInterface(type.getModifiers())) { - throw new IllegalArgumentException("type ["+ type +"] is not a interface type."); - } - return (T) Proxy.newProxyInstance(type.getClassLoader(), new Class[]{type}, (p, m, o) -> proxyHandler.apply(m, o)); - } - - /** - * 为一个接口类型创建动态代理对象。 - * @param type 接口的类型 - * @param proxyHandler 动态代理的逻辑处理类 - * @param - * @return - */ - public static T proxy(Class type, InvocationHandler proxyHandler){ - if (!Modifier.isInterface(type.getModifiers())) { - throw new IllegalArgumentException("type ["+ type +"] is not a interface type."); - } - return (T) Proxy.newProxyInstance(type.getClassLoader(), new Class[]{type}, proxyHandler); - } - - - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/RandomUtil.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/RandomUtil.java deleted file mode 100644 index 0981e0f..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/RandomUtil.java +++ /dev/null @@ -1,365 +0,0 @@ -package io.fluent.mocker.utils; - -import java.awt.*; -import java.text.DecimalFormat; -import java.util.List; -import java.util.Objects; -import java.util.Random; -import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; - -/** - * 随机值获取工具类 - * @author ForteScarlet - */ -public class RandomUtil { - - /** - * 保存一个单例Random - */ - private static final Random LOCAL_RANDOM = new Random(); - - /** - * 获取一个Random实例。 - * 是一个线程ThreadLocalRandom对象。 - */ - public static ThreadLocalRandom getRandom() { - return ThreadLocalRandom.current(); - } - - /** - * 获取一个单例的Random对象。 - */ - public static Random getLocalRandom() { - return LOCAL_RANDOM; - } - - /* ——————————————————————— getNumber : 获取随机长度字母(仅数字,尽量不要超过int的最大数上限长度) ——————————————————————————— */ - - /** - * 获取长度为4的随机数 - * - * @return - */ - public static int getNumber() { - return getNumber(4); - } - - /** - * 获取指定长度的随机数 - * @param length 数字的长度 - * @return - */ - public static int getNumber(int length) { - length--; - int pow = (int) Math.pow(10, length); - ThreadLocalRandom random = getRandom(); - if (length >= 1) { - //参照算法:random.nextInt(9000)+1000; - //(9 * pow) - int nextInt = (pow << 3) + pow; - return (random.nextInt(nextInt) + pow); - } else { - return random.nextInt(10); - } - } - - /** - * 获取一个随机整数 - * - * @return - */ - public static int getInteger() { - return getRandom().nextInt(10); - } - - /** - * 获取某个区间中的随机数[a,b) - * - * @return - */ - public static int getNumber(int a, int b) { - return getRandom().nextInt(a, b); - } - - - /** - * 获取某个区间中的随机数[a,b] - * - * @param a min number - * @param b max number - */ - public static int getNumberWithRight(int a, int b) { - return getNumber(a, b+1); - } - - /** - * @see #getNumberWithRight(int, int) - */ - @Deprecated - public static int getNumber$right(int a, int b) { - return getNumberWithRight(a, b); - } - - - /* ——————————————————————— getCode : 获取随机code(字母和数字) ——————————————————————————— */ - - - /** - * 获取随机code,包含数字和字母 - * - * @param length - * @return - */ - public static String getCode(int length) { - StringBuilder s = new StringBuilder(length); - Random r = getRandom(); - for (int i = 1; i <= length; i++) { - if (r.nextBoolean()) { - //0.5的概率为0-9的数字 - s.append(r.nextInt()); - } else { - //0.5的概率为字母,其中大写0.25,小写0.25 - if (r.nextBoolean()) { - //小写 - s.append(getRandomChar()); - } else { - //大写 - s.append(Character.toUpperCase(getRandomChar())); - } - } - } - return s.toString(); - } - - /** - * 获取一个4位数的随机code,字母小写 - * - * @return - */ - public static String getCode() { - return getCode(4); - } - - - /* ——————————————————————— getUUID : 获取随机UUID,java.util自带的UUID方法 ——————————————————————————— */ - - - /** - * 获取UUID.toString - * - * @return - */ - public static String getUUID() { - return UUID.randomUUID().toString(); - } - - - /* ——————————————————————— getRandomChar : 获取随机字符(单个字母) ——————————————————————————— */ - - /** - * 获取一个随机英文字符,小写 - */ - public static char getRandomChar() { - return (char) (RandomUtil.getRandom().nextInt(26) + 97); - } - - /** - * 获取一个随机英文字符,大写 - */ - public static char getRandomUpperChar() { - return (char) (RandomUtil.getRandom().nextInt(26) + 65); - } - - - /* ———————————————————— getRandomString : 获取随机字符串 ———————————————————————— */ - - /** - * 得到一串纯大写的字符串 - * @param length 字符串长度 - */ - public static String getRandomUpperString(int length){ - char[] crr = new char[length]; - for (int i = 0; i < length; i++) { - crr[i] = getRandomUpperChar(); - } - return String.valueOf(crr); - } - - /** - * 获取一串指定长度的随机字符串 - * - * @param length 字符串长度 - * @param randomCase 是否开启随机大小写 - * @return - */ - public static String getRandomString(int length, boolean randomCase) { - char[] crr = new char[length]; - for (int i = 0; i < length; i++) { - //如果开启了随机大写,则有概率将字符转为大写 1/2 - if (randomCase) { - crr[i] = RandomUtil.getRandom().nextBoolean() ? getRandomChar() : getRandomUpperChar(); - } else { - crr[i] = getRandomChar(); - } - } - return String.valueOf(crr); - } - - /** - * 获取一串指定长度的随机字符串,默认小写 - * - * @param length 字符串长度 - * @return - */ - public static String getRandomString(int length) { - return getRandomString(length, false); - } - - - /** - * 获取一串长度为32的字符串,默认小写 - */ - public static String getRandomString() { - return getRandomString(32, false); - } - - /** - * 数字小数保留 - * - * @param dnum 需要保留的小数 - * @param length 小数保留位数 - * @return - */ - public static String toFixed(Number dnum, int length) { - StringBuilder sb = new StringBuilder(2 + length).append("#."); - //遍历并设置位数 - for (int i = 0; i < length; i++) { - sb.append('0'); - } - - //返回结果 - String formatStr = sb.toString(); - sb = new StringBuilder(); - String douStr = numFormat(dnum, formatStr); - sb.append(douStr); - if(douStr.startsWith(".")){ - //如果开头是点,说明首位是0,补位 - sb.append('0').append(douStr); - } - return sb.toString(); - } - - - /** - * 自定义数字格式化 - * - * @param dnum - * @param formatStr - * @return - */ - public static String numFormat(Number dnum, String formatStr) { - return new DecimalFormat(formatStr).format(dnum); - } - - /* ———————————————————— getColor : 获取随机颜色 ———————————————————————— */ - - /** - * 返回一个随机颜色 - * - * @return - */ - public static Color randomColor() { - int[] arr = randomColor$intArr(); - return new Color(arr[0], arr[1], arr[2]); - } - - /** - * 返回一个长度为三的数组,三位分别代表了颜色的R、G、B - * - * @return - */ - public static int[] randomColor$intArr() { - final int[] arr = new int[3]; - Random random = RandomUtil.getRandom(); - arr[0] = random.nextInt(256); - arr[1] = random.nextInt(256); - arr[2] = random.nextInt(256); - return arr; - } - - /** - * 返回16进制颜色代码 - * - * @return - */ - public static String randomColor$hexString() { - int[] arr = randomColor$intArr(); - StringBuilder sb = new StringBuilder(); - String r = Integer.toHexString(arr[0]); - r = r.length() == 1 ? '0' + r : r; - - String g = Integer.toHexString(arr[1]); - g = g.length() == 1 ? '0' + g : g; - - String b = Integer.toHexString(arr[2]); - b = b.length() == 1 ? '0' + b : b; - sb.append("#") - .append(r) - .append(g) - .append(b); - return sb.toString(); - } - - /* ———————————————————— getProbability : 根据概率获取boolean ———————————————————————— */ - - /** - * 根据概率获取boolean,区间:[probL , probR] - * - * @param probL 概率百分比区间的左参数,取值范围为0-1之间,对应了0%和100% - * @param probR 概率百分比区间的右参数,取值范围为0-1之间,对应了0%和100% - * @return - */ - public static Boolean getProbability(double probL, double probR) { - double v = RandomUtil.getRandom().nextDouble(); - if (v >= probL && v <= probR) { - return true; - } - return false; - } - - /** - * 根据概率获取boolean,区间:[0 , prob] - * 填入的参数即为概率的百分比 - * - * @param prob 概率百分比的小数形式,参数范围0-1 - * @return - */ - public static Boolean getProbability(double prob) { - return getProbability(0, prob); - } - - /* ———————————————————— getRandomElement : 从数组或者集合中获取一个随机元素 ———————————————————————— */ - - /** - * 从数组中返回一个随机元素 - * @param trr 数组 - * @return 随机元素 - */ - public static T getRandomElement(T[] trr) { - Objects.requireNonNull(trr); - return trr.length == 0 ? null : trr[RandomUtil.getRandom().nextInt(trr.length)]; - } - - /** - * 从集合中返回一个随机元素, ru如果数组为空则返回null - * @param trr 集合 - * @return 随机元素 - */ - public static T getRandomElement(List trr) { - Objects.requireNonNull(trr); - return trr.size() == 0 ? null : trr.get(RandomUtil.getRandom().nextInt(trr.size())); - } - - -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/RegexUtil.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/RegexUtil.java deleted file mode 100644 index ae7a537..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/RegexUtil.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.fluent.mocker.utils; - -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * 正则表达式匹配两个字符串之间的内容 - * 代码来源于网络 - * - * @author 来源:https://www.cnblogs.com/jimmy-c/p/4139664.html - */ -public class RegexUtil { - - public static List getMatcher(String source, String regex) { - - /* - Pattern: 一个Pattern是一个正则表达式经编译后的表现模式。 - Matcher: 一个Matcher对象是一个状态机器,它依据Pattern对象做为匹配模式对字符串展开匹配检查。 - */ - Pattern pattern = Pattern.compile(regex); - Matcher matcher = pattern.matcher(source); - //记录匹配的数量并创建数组 - List end = new ArrayList<>(); - //遍历并保存结果集 - while (matcher.find()) { - end.add(matcher.group()); - } - //返回结果 - return end; - } -} diff --git a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/SingleFactory.java b/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/SingleFactory.java deleted file mode 100644 index b778adb..0000000 --- a/modules/fluent-mocker/src/main/java/io/fluent/mocker/utils/SingleFactory.java +++ /dev/null @@ -1,347 +0,0 @@ -package io.fluent.mocker.utils; - -import java.lang.reflect.InvocationTargetException; -import java.util.*; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Supplier; - -/** - * 基于CAS原理的单例工厂,提供了丰富的方法来记录或获取一个单例实例
- * 单例原理为基于CAS的乐观锁懒汉式单例
- * 方法内全部为final类型的静态方法,所以本类为抽象类且没有继承的必要
- * @author ForteScarlet <[163邮箱地址]ForteScarlet@163.com> - * @date 2018/12/19 15:59 - * @version 2.0 - * @since JDK1.8 - **/ -public abstract class SingleFactory { - - /** - * 单例仓库-线程安全Map - */ - private static final Map SINGLE_MAP = Collections.synchronizedMap(new HashMap<>()); - - /** - * 获取单例,如果没有此类的记录则返回空 - */ - public static final T get(Class clz){ - return Optional.ofNullable(SINGLE_MAP.get(clz)).map(s -> (T)s.get()).orElse(null); - } - - /** - * 获取单例,如果没有则尝试使用反射获取一个新的,将会被记录。 - * 如果创建失败将会抛出相应的异常 - * @param - * @return - */ - public static final T getOrNew(Class clz){ - return getOrNew(clz, (Object[]) null); - } - - public static final T getOrNew(Class clz , Object... params){ - return Optional.ofNullable(SINGLE_MAP.get(clz)).map(s -> (T)s.get()).orElseGet(() -> { - //如果没有,记录 - return set(clz, () -> { - try { - //判断参数数量 - if(params != null && params.length > 0){ - //如果数量大于0 - //获取参数的class数组 - Class[] classes = Arrays.stream(params).map(Object::getClass).toArray(Class[]::new); - //尝试使用反射获取一个新对象 - return clz.getConstructor(classes).newInstance(params); - }else{ - //没有参数,直接获取 - return clz.newInstance(); - } - } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { - throw new RuntimeException(e); - } - }, false).get(); - }); - } - - - /** - * 如果存在则获取,不存在则赋值 - * @param clz - * @param t - * @param - * @return - */ - public static final T getOrSet(Class clz, T t){ - return Optional.ofNullable((T)get(clz)).orElseGet(() -> setAndGet(clz, t)); - } - - /** - * 如果存在则获取,不存在则赋值,不指定class对象 - * @param t - * @param - * @return - */ - public static final T getOrSet(T t){ - return Optional.ofNullable((T)get(t.getClass())).orElseGet(() -> setAndGet(t)); - } - - - /** - * 如果存在则获取,不存在则赋值 - * @param clz - * @param supplier - * @param - * @return - */ - public static final T getOrSet(Class clz, Supplier supplier){ - return Optional.ofNullable((T)get(clz)).orElseGet(() -> setAndGet(clz, supplier)); - } - - /** - * 如果存在则获取,不存在则赋值,不指定class对象 - * @param supplier - * @param - * @return - */ - public static final T getOrSet(Supplier supplier){ - return Optional.ofNullable((T)get(supplier.get().getClass())).orElseGet(() -> setAndGet(supplier)); - } - - /** - * 重设一个单例 - * @param clz - * @param t - * @param - */ - public static final void reset(Class clz , T t){ - set(clz, t, true); - } - - - /** - * 重设一个单例,不指定class - * @param t - * @param - */ - public static final void reset(T t){ - reset(t.getClass(), t); - } - - /** - * 重设一个单例并获取单例实例 - * @param clz - * @param t - * @param - * @return - */ - public static final T resetAndGet(Class clz , T t){ - return set(clz, t, true).get(); - } - - - /** - * 重设一个单例并获取单例实例,不指定class - * @param t - * @param - * @return - */ - public static final T resetAndGet(T t){ - return resetAndGet((Class)t.getClass(), t); - } - - /** - * 重设一个单例 - * @param clz - * @param supplier - * @param - */ - public static final void reset(Class clz , Supplier supplier){ - set(clz, supplier, true); - } - - - /** - * 重设一个单例,不指定class - * @param supplier - * @param - */ - public static final void reset(Supplier supplier){ - reset(supplier.get().getClass(), supplier); - } - - /** - * 重设一个单例并获取单例实例 - * @param clz - * @param supplier - * @param - * @return - */ - public static final T resetAndGet(Class clz , Supplier supplier){ - return set(clz, supplier, true).get(); - } - - /** - * 重设一个单例并获取单例实例,不指定class - * @param supplier - * @param - * @return - */ - public static final T resetAndGet(Supplier supplier){ - return resetAndGet((Class)supplier.get().getClass(), supplier); - } - - - /** - * 记录一个单例 - * @param clz - * @param t - * @param - */ - public static final void set(Class clz , T t){ - set(clz, t, false); - } - - /** - * 记录一个单例,不指定class - * @param t - * @param - */ - public static final void set(T t){ - set(t.getClass(), t); - } - - /** - * 记录一个单例并获取单例实例 - * @param clz - * @param t - * @param - * @return - */ - public static final T setAndGet(Class clz , T t){ - return set(clz, t, false).get(); - } - - - /** - * 记录一个单例并获取单例实例,不指定class - * @param t - * @param - * @return - */ - public static final T setAndGet(T t){ - return setAndGet((Class)t.getClass(), t); - } - - /** - * 记录一个单例 - * @param clz - * @param supplier - * @param - */ - public static final void set(Class clz , Supplier supplier){ - set(clz, supplier, false); - } - - /** - * 记录一个单例,不指定class - * @param supplier - * @param - */ - public static final void set(Supplier supplier){ - set(supplier.get().getClass(), supplier); - } - - /** - * 记录一个单例并获取单例实例 - * @param clz - * @param supplier - * @param - * @return - */ - public static final T setAndGet(Class clz , Supplier supplier){ - return set(clz, supplier, false).get(); - } - - /** - * 记录一个单例,不指定class - * @param supplier - * @param - * @return - */ - public static final T setAndGet(Supplier supplier){ - return setAndGet((Class)supplier.get().getClass(), supplier); - } - - - /** - * 记录一个单例对象或重设一个单例-对象 - * @param clz - * @param t - * @param - */ - private static final SingleBean set(Class clz , T t , boolean reset){ - return set(clz , () -> t , reset); - } - - /** - * 记录一个单例对象或重设一个单例-函数接口 - * 赋值相关重载方法的根方法 - * 使用synchronized标记 - * @param clz - * @param supplier - * @param - */ - private static synchronized final SingleBean set(Class clz , Supplier supplier , boolean reset){ - SingleBean singleBean = SINGLE_MAP.get(clz); - if(!reset && singleBean != null){ - //如果已经存在,直接返回此对象 - return singleBean; - } - - //创建新对象 - singleBean = new SingleBean<>(supplier); - SINGLE_MAP.put(clz, singleBean); - return singleBean; - } - - - /** - * 内部单例类,应当是基于CAS原理的懒汉式单例类 - * @param - */ - private static final class SingleBean { - /** - * 获取实例的方法 - */ - private final Supplier supplier; - private AtomicReference single = new AtomicReference<>(); - - /** - * 获取单例 - */ - private T get() { - for (;;) { - //获取 - T currect = single.get(); - //如果存在直接返回 - if (currect != null) { - return currect; - } - //创建 - currect = supplier.get(); - //原子赋值 - if (single.compareAndSet(null, currect)) { - return currect; - } - } - } - - /** - * 构造 - * - * @param supplier - */ - private SingleBean(Supplier supplier) { - this.supplier = supplier; - } - } - -} diff --git a/modules/fluent-spring/pom.xml b/modules/fluent-spring/pom.xml index b7c1679..367bee5 100644 --- a/modules/fluent-spring/pom.xml +++ b/modules/fluent-spring/pom.xml @@ -32,6 +32,14 @@ spring-webmvc 6.1.11 + + + jakarta.servlet + jakarta.servlet-api + 6.1.0 + provided + + org.springframework diff --git a/modules/fluent-spring/src/main/java/io/fluent/spring/filter/CORSFilter.java b/modules/fluent-spring/src/main/java/io/fluent/spring/filter/CORSFilter.java new file mode 100644 index 0000000..52f333b --- /dev/null +++ b/modules/fluent-spring/src/main/java/io/fluent/spring/filter/CORSFilter.java @@ -0,0 +1,26 @@ +package io.fluent.spring.filter; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; +import java.io.IOException; + +/** + */ +@Component +public class CORSFilter extends OncePerRequestFilter { + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("Access-Control-Allow-Credentials", "true"); + response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT"); + response.setHeader("Access-Control-Max-Age", "3600"); + response.setHeader("Access-Control-Allow-Headers", "Authorization,Origin,X-Requested-With,token,Content-Type,Accept,Access-Token,platform,latitude,longitude,storeId,merchantNo,isWechat"); + filterChain.doFilter(request, response); + } + +} diff --git a/modules/fluent-spring/src/main/java/io/fluent/spring/interceptors/CommandInterceptor.java b/modules/fluent-spring/src/main/java/io/fluent/spring/interceptors/CommandInterceptor.java new file mode 100644 index 0000000..58a12ea --- /dev/null +++ b/modules/fluent-spring/src/main/java/io/fluent/spring/interceptors/CommandInterceptor.java @@ -0,0 +1,20 @@ +package io.fluent.spring.interceptors; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.util.StringUtils; +import org.springframework.web.servlet.AsyncHandlerInterceptor; + +public class CommandInterceptor implements AsyncHandlerInterceptor { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + String serverName = request.getServerName(); + if (StringUtils.hasText( + serverName) && serverName.equals("localhost")) { + return true; + } else { + return false; + } + } +} \ No newline at end of file diff --git a/modules/fluent-spring/src/main/java/io/fluent/spring/util/SpringUtils.java b/modules/fluent-spring/src/main/java/io/fluent/spring/util/SpringUtils.java index b53eded..2914548 100644 --- a/modules/fluent-spring/src/main/java/io/fluent/spring/util/SpringUtils.java +++ b/modules/fluent-spring/src/main/java/io/fluent/spring/util/SpringUtils.java @@ -18,7 +18,6 @@ /** * spring工具类 方便在非spring管理环境中获取bean - * */ public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware { diff --git a/package.sh b/package.sh index 8a39808..4c2fbf9 100644 --- a/package.sh +++ b/package.sh @@ -1,2 +1 @@ - mvn clean package -Dmaven.test.skip=true - cp -rf server/target/*.jar . \ No newline at end of file + mvn clean package -Dmaven.test.skip=true \ No newline at end of file diff --git a/pom.xml b/pom.xml index f018d60..6bf4e89 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ - 1.12.15 + 1.12.19 1.0-SNAPSHOT 42.7.2 2.7.18