Browse Source

Merge remote-tracking branch 'finekit/master'

master
Mars.Ma 5 years ago
parent
commit
5db6bb9c21
  1. 32
      pom.xml
  2. 24
      readme.md
  3. 37
      src/main/java/com/fanruan/api/cal/ContainerKit.java
  4. 4
      src/main/java/com/fanruan/api/cal/FormulaKit.java
  5. 48
      src/main/java/com/fanruan/api/cal/ParameterKit.java
  6. 14
      src/main/java/com/fanruan/api/conf/BaseConfiguration.java
  7. 22
      src/main/java/com/fanruan/api/consts/EncodeConstantsKit.java
  8. 38
      src/main/java/com/fanruan/api/data/ConnectionKit.java
  9. 4
      src/main/java/com/fanruan/api/data/connection/NameDatabaseConnection.java
  10. 20
      src/main/java/com/fanruan/api/design/DesignKit.java
  11. 8
      src/main/java/com/fanruan/api/design/ui/action/UpdateAction.java
  12. 28
      src/main/java/com/fanruan/api/design/ui/component/UICheckBox.java
  13. 115
      src/main/java/com/fanruan/api/design/ui/component/UIComboBox.java
  14. 4
      src/main/java/com/fanruan/api/design/ui/component/UIDescriptionTextArea.java
  15. 14
      src/main/java/com/fanruan/api/design/ui/component/UIDictionaryComboBox.java
  16. 24
      src/main/java/com/fanruan/api/design/ui/component/UIIntNumberField.java
  17. 191
      src/main/java/com/fanruan/api/design/ui/component/UILazyComboBox.java
  18. 45
      src/main/java/com/fanruan/api/design/ui/component/UINumberField.java
  19. 19
      src/main/java/com/fanruan/api/design/ui/component/UIPasswordField.java
  20. 27
      src/main/java/com/fanruan/api/design/ui/component/UIPlaceholderTextField.java
  21. 18
      src/main/java/com/fanruan/api/design/ui/component/UISpinner.java
  22. 35
      src/main/java/com/fanruan/api/design/ui/component/UITable.java
  23. 14
      src/main/java/com/fanruan/api/design/ui/component/UIToolbar.java
  24. 35
      src/main/java/com/fanruan/api/design/ui/component/code/SyntaxConstants.java
  25. 37
      src/main/java/com/fanruan/api/design/ui/component/code/UISyntaxTextArea.java
  26. 30
      src/main/java/com/fanruan/api/design/ui/component/code/UISyntaxTextScrollPane.java
  27. 45
      src/main/java/com/fanruan/api/design/ui/component/formula/UIFormulaTextField.java
  28. 21
      src/main/java/com/fanruan/api/design/ui/component/table/UITableEditorPane.java
  29. 3
      src/main/java/com/fanruan/api/design/ui/component/table/action/UITableEditAction.java
  30. 334
      src/main/java/com/fanruan/api/design/ui/component/table/model/ParameterTableModel.java
  31. 62
      src/main/java/com/fanruan/api/design/ui/component/table/model/UITableModelAdapter.java
  32. 4
      src/main/java/com/fanruan/api/design/ui/container/BasicBeanPane.java
  33. 36
      src/main/java/com/fanruan/api/design/ui/container/BasicDialog.java
  34. 8
      src/main/java/com/fanruan/api/design/ui/container/DialogActionAdapter.java
  35. 16
      src/main/java/com/fanruan/api/design/ui/container/UIScrollPane.java
  36. 445
      src/main/java/com/fanruan/api/design/ui/editor/ValueEditors.java
  37. 31
      src/main/java/com/fanruan/api/design/util/I18nDesignKit.java
  38. 9
      src/main/java/com/fanruan/api/design/work/ConnectionComboBoxPanel.java
  39. 7
      src/main/java/com/fanruan/api/design/work/DatabaseConnectionPane.java
  40. 4
      src/main/java/com/fanruan/api/err/UtilEvalError.java
  41. 48
      src/main/java/com/fanruan/api/macro/EncodeConstants.java
  42. 677
      src/main/java/com/fanruan/api/net/http/HttpKit.java
  43. 54
      src/main/java/com/fanruan/api/net/http/rs/BaseHttpResponseHandle.java
  44. 215
      src/main/java/com/fanruan/api/net/http/rs/HttpRequest.java
  45. 114
      src/main/java/com/fanruan/api/net/http/rs/HttpRequestType.java
  46. 103
      src/main/java/com/fanruan/api/net/http/rs/HttpResponseType.java
  47. 55
      src/main/java/com/fanruan/api/net/http/rs/StreamResponseHandle.java
  48. 39
      src/main/java/com/fanruan/api/net/http/rs/TextResponseHandle.java
  49. 48
      src/main/java/com/fanruan/api/net/http/rs/UploadResponseHandle.java
  50. 14
      src/main/java/com/fanruan/api/script/ScriptKit.java
  51. 16
      src/main/java/com/fanruan/api/util/ReflectKit.java
  52. 32
      src/main/java/com/fanruan/api/util/TypeKit.java
  53. 39
      src/main/java/com/fanruan/api/xml/XmlKit.java
  54. 24
      src/test/java/com/fanruan/api/cal/ContainerKitTest.java
  55. 60
      src/test/java/com/fanruan/api/cal/ParameterKitTest.java
  56. 153
      src/test/java/com/fanruan/api/net/http/HttpKitTest.java
  57. 30
      src/test/java/com/fanruan/api/util/GeneralKitTest.java
  58. 14
      src/test/java/com/fanruan/api/util/ReflectKitTest.java
  59. 19
      src/test/java/com/fanruan/api/util/TypeKitTest.java

32
pom.xml

@ -6,7 +6,7 @@
<version>10.0</version> <version>10.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<properties> <properties>
<common-version>10.0-PERSIST-SNAPSHOT</common-version> <common-version>10.0-FEATURE-SNAPSHOT</common-version>
<maven.build.timestamp.format>yyyyMMdd</maven.build.timestamp.format> <maven.build.timestamp.format>yyyyMMdd</maven.build.timestamp.format>
<build-version>${version}</build-version> <build-version>${version}</build-version>
<build-no>${maven.build.timestamp}</build-no> <build-no>${maven.build.timestamp}</build-no>
@ -121,6 +121,12 @@
<version>1.7.1</version> <version>1.7.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
<version>4.0.1</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
<finalName>${project.artifactId}-${version}-${maven.build.timestamp}</finalName> <finalName>${project.artifactId}-${version}-${maven.build.timestamp}</finalName>
@ -162,4 +168,28 @@
</resource> </resource>
</resources> </resources>
</build> </build>
<repositories>
<repository>
<id>fanruan</id>
<name>fanruan</name>
<url>http://mvn.finedevelop.com/repository/maven-public/</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>fanruan</id>
<name>fanruan</name>
<url>http://mvn.finedevelop.com/repository/maven-public/</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project> </project>

24
readme.md

@ -24,7 +24,7 @@ SessionKit#getSession(@NotNull String sessionID);
## 提交新API要求 ## 提交新API要求
* 所有的API方法的返回值和参数,仅允许使用基本类型、接口类型或者使用了@Open标记的对象类型。 * 所有的API方法的返回值和参数,仅允许使用JDK自带的类、接口类型、插件抽象类、注解或者使用了@Open标记的对象类型。
* 所有的API方法均需要有单元测试覆盖。 * 所有的API方法均需要有单元测试覆盖。
@ -39,3 +39,25 @@ SessionKit#getSession(@NotNull String sessionID);
``` ```
会在target目录下获得一个形如finekit-10.0-20190815.jar名字jar包,直接作为插件依赖jar包即可。 会在target目录下获得一个形如finekit-10.0-20190815.jar名字jar包,直接作为插件依赖jar包即可。
## 已完全依赖FineKit的插件
|插件名|源码|
|-----|----|
|redis数据集插件|https://git.fanruan.com/fanruan/demo-tabledata-redis|
|增强公式编辑器插件|https://git.fanruan.com/fanruan/demo-formula-script
|条件属性之文本对齐插件|https://git.fanruan.com/fanruan/demo-highlight-align|
## 如何判断插件中调用的API需要增加到FineKit中
最简单的原则:除了JDK自带的类、插件接口(包括抽象类)、以及使用了@Open注解标记的类之外,是否还使用了com.fanruan.api(com.fr.third除外)之外的类,如果有则需要修改。
## 如何提交新的API
1、先访问[https://git.fanruan.com](https://git.fanruan.com)并注册一个自己的账号;
2、然后将[https://git.fanruan.com/fanruan/finekit](https://git.fanruan.com/fanruan/finekit) fork到自己账户下;
3、克隆FineKit代码到本地,新增相关的API代码,并提交到自己的仓库;
4、提交Pull Request到FineKit主仓库,等待审核通过被合并即可。

37
src/main/java/com/fanruan/api/cal/ContainerKit.java

@ -0,0 +1,37 @@
package com.fanruan.api.cal;
import com.fr.general.FArray;
import com.fr.stable.ArrayProvider;
import java.util.Collection;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-29
* 创建容器的工具类
*/
public class ContainerKit {
/**
* 创建一个插件可识别的数组对象
*
* @param array 原始数组
* @param <T> 数组元素类型
* @return 插件可识别的数组对象
*/
public static <T> ArrayProvider<T> newArray(T[] array) {
return new FArray<>(array);
}
/**
* 创建一个插件可识别的数组对象
*
* @param collection 原始集合
* @param <T> 数组元素类型
* @return 插件可识别的数组对象
*/
public static <T> ArrayProvider<T> newArray(Collection<T> collection) {
return new FArray<>(collection);
}
}

4
src/main/java/com/fanruan/api/cal/FormulaKit.java

@ -16,8 +16,8 @@ import org.jetbrains.annotations.Nullable;
/** /**
* @author richie * @author richie
* @version 10.0 * @version 10.0
* Created by richie on 2019-08-15 * Created by richie on 2019-08-15
* 公式计算相关的工具类 * 公式计算相关的工具类
*/ */
public class FormulaKit { public class FormulaKit {

48
src/main/java/com/fanruan/api/cal/ParameterKit.java

@ -1,8 +1,8 @@
package com.fanruan.api.cal; package com.fanruan.api.cal;
import com.fr.base.Parameter;
import com.fr.base.ParameterHelper; import com.fr.base.ParameterHelper;
import com.fr.base.ParameterMapNameSpace; import com.fr.base.ParameterMapNameSpace;
import com.fr.script.CalculatorMap;
import com.fr.stable.ParameterProvider; import com.fr.stable.ParameterProvider;
import com.fr.stable.script.NameSpace; import com.fr.stable.script.NameSpace;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -15,19 +15,54 @@ import java.util.Map;
* Created by richie on 2019-08-16 * Created by richie on 2019-08-16
* 参数相关的工具类 * 参数相关的工具类
*/ */
public class ParameterKit{ public class ParameterKit {
/**
* 创建一个参数对象实例
*
* @return 参数对象
*/
public static ParameterProvider newParameter() {
return new Parameter();
}
/**
* 创建一个参数对象实例
*
* @param name 参数名
* @param value 参数值
* @return 参数对象
*/
public static ParameterProvider newParameter(String name, Object value) {
return new Parameter(name, value);
}
/**
* 从字符串中分析中有哪些需要的参数
*
* @param text 字符串
* @param hasColumnRow 是否需要分析格子类型的参数
* @return 字符串中包含的参数集合
*/
public static Parameter[] analyze4Parameters(String text, boolean hasColumnRow) {
return ParameterHelper.analyze4Parameters(text, hasColumnRow);
}
/** /**
* 分析公式中所携带的参数 * 分析公式中所携带的参数
*
* @param text 公式内容 * @param text 公式内容
* @return 参数数组 * @return 参数数组
*/ */
public static @NotNull ParameterProvider[] analyze4ParametersFromFormula(String text) { public static @NotNull ParameterProvider[] analyze4ParametersFromFormula(String text) {
return ParameterHelper.analyze4ParametersFromFormula(text); return ParameterHelper.analyze4ParametersFromFormula(text);
} }
/** /**
* 分析一组字符串中的参数 * 分析一组字符串中的参数
*
* @param paramTexts 字符串组 * @param paramTexts 字符串组
* @param isFormula 是否是公式类型的字符串数组 * @param isFormula 是否是公式类型的字符串数组
* @return 参数集合 * @return 参数集合
*/ */
public static @NotNull ParameterProvider[] analyze4Parameters(String[] paramTexts, boolean isFormula) { public static @NotNull ParameterProvider[] analyze4Parameters(String[] paramTexts, boolean isFormula) {
@ -36,19 +71,22 @@ public class ParameterKit{
/** /**
* 创建一个用于计算的参数对名字空间 * 创建一个用于计算的参数对名字空间
*
* @param map 参数键值对 * @param map 参数键值对
* @return 名字空间用于传递给算子做计算 * @return 名字空间用于传递给算子做计算
*/ */
public static @NotNull NameSpace createParameterMapNameSpace(Map<String, Object> map) { public static @NotNull NameSpace createParameterMapNameSpace(Map<String, Object> map) {
return ParameterMapNameSpace.create(map); return ParameterMapNameSpace.create(map);
} }
/** /**
* 创建一个用于计算的参数对名字空间 * 创建一个用于计算的参数对名字空间
* @param ps ParameterProvider的数组 *
* @param ps 参数数组数组
* @return 名字空间用于传递给算子做计算 * @return 名字空间用于传递给算子做计算
*/ */
public static @NotNull ParameterMapNameSpace createParameterProvider(ParameterProvider[] ps) { public static @NotNull ParameterMapNameSpace createParameterMapNameSpace(ParameterProvider[] ps) {
return ParameterMapNameSpace.create(ps); return ParameterMapNameSpace.create(ps);
} }
} }

14
src/main/java/com/fanruan/api/conf/BaseConfiguration.java

@ -7,6 +7,20 @@ import com.fr.config.DefaultConfiguration;
* @author richie * @author richie
* @version 10.0 * @version 10.0
* Created by richie on 2019-08-16 * Created by richie on 2019-08-16
* 插件要实现配置类的时候直接继承该抽象类即可
* <p>
* private static class MyConf extends BaseConfiguration {
*
* private static volatile MyConf instance = null;
*
* public static MyConf getInstance() {
* if (instance == null) {
* instance = getConfigInstance(MyConf.class);
* }
* return instance;
* }
* }
* <p/>
*/ */
public abstract class BaseConfiguration extends DefaultConfiguration { public abstract class BaseConfiguration extends DefaultConfiguration {

22
src/main/java/com/fanruan/api/consts/EncodeConstantsKit.java

@ -1,22 +0,0 @@
package com.fanruan.api.consts;
import com.fr.stable.EncodeConstants;
public class EncodeConstantsKit {
public static final String ENCODING_UTF_8 = EncodeConstants.ENCODING_UTF_8;
public static final String ENCODING_GBK = EncodeConstants.ENCODING_GBK;
public static final String ENCODING_BIG5 = EncodeConstants.ENCODING_BIG5;
public static final String ENCODING_ISO_8859_1 = EncodeConstants.ENCODING_ISO_8859_1;
public static final String ENCODING_UTF_16 = EncodeConstants.ENCODING_UTF_16;
public static final String ENCODING_EUC_JP = EncodeConstants.ENCODING_EUC_JP;
public static final String ENCODING_EUC_KR = EncodeConstants.ENCODING_EUC_KR;
public static final String ENCODING_CP850 = EncodeConstants.ENCODING_CP850;
}

38
src/main/java/com/fanruan/api/data/ConnectionKit.java

@ -0,0 +1,38 @@
package com.fanruan.api.data;
import com.fanruan.api.util.TypeKit;
import com.fr.data.impl.Connection;
import com.fr.file.ConnectionConfig;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* 数据连接相关工具类
*/
public class ConnectionKit {
/**
* 获取指定名字的数据连接
*
* @param name 名字
* @return 数据连接
*/
public @Nullable Connection getConnection(@NotNull String name) {
return ConnectionConfig.getInstance().getConnection(name);
}
/**
* 获取指定名字和指定类型的数据连接
*
* @param name 数据连接的名字
* @param type 类型
* @return 数据连接
*/
public <T extends Connection> @Nullable T getConnection(@NotNull String name, Class<? extends Connection> type) {
Connection connection = getConnection(name);
if (TypeKit.objectInstanceOf(connection, type)) {
return (T) connection;
}
return null;
}
}

4
src/main/java/com/fanruan/api/data/connection/NameDatabaseConnection.java

@ -0,0 +1,4 @@
package com.fanruan.api.data.connection;
public class NameDatabaseConnection extends com.fr.data.impl.NameDatabaseConnection{
}

20
src/main/java/com/fanruan/api/design/DesignKit.java

@ -2,6 +2,7 @@ package com.fanruan.api.design;
import com.fr.base.TableData; import com.fr.base.TableData;
import com.fr.design.data.datapane.preview.PreviewTablePane; import com.fr.design.data.datapane.preview.PreviewTablePane;
import com.fr.design.i18n.Toolkit;
public class DesignKit { public class DesignKit {
/** /**
@ -11,4 +12,23 @@ public class DesignKit {
public static void previewTableData(TableData tableData){ public static void previewTableData(TableData tableData){
PreviewTablePane.previewTableData(tableData, -1, -1); PreviewTablePane.previewTableData(tableData, -1, -1);
} }
/**
* 文本国际化
* @param key 国际化键
* @return 国际化后的值
*/
public static String i18nText(String key) {
return Toolkit.i18nText(key);
}
/**
* 带参数的文本国际化
* @param key 国际化键
* @param args 参数
* @return 国际化后的值
*/
public static String i18nText(String key, Object... args) {
return Toolkit.i18nText(key, args);
}
} }

8
src/main/java/com/fanruan/api/design/ui/action/UpdateAction.java

@ -1,8 +1,8 @@
package com.fanruan.api.design.ui.action; package com.fanruan.api.design.ui.action;
import java.awt.event.ActionEvent; /**
* 用于各种菜单动作实现的抽象类
*/
public abstract class UpdateAction extends com.fr.design.actions.UpdateAction {
public class UpdateAction extends com.fr.design.actions.UpdateAction{
@Override
public void actionPerformed(ActionEvent evt) {}
} }

28
src/main/java/com/fanruan/api/design/ui/component/UICheckBox.java

@ -0,0 +1,28 @@
package com.fanruan.api.design.ui.component;
import javax.swing.*;
/**
* @author zhaojunzhe
* @version 10.0
* Created by zhaojunzhe on 2019-08-28
* 复选框组件
*/
public class UICheckBox extends com.fr.design.gui.icheckbox.UICheckBox {
public UICheckBox() {
}
public UICheckBox(String text) {
super(text);
}
public UICheckBox(String text, boolean checked) {
super(text, checked);
}
public UICheckBox(String text, Icon icon) {
super(text, icon);
}
}

115
src/main/java/com/fanruan/api/design/ui/component/UIComboBox.java

@ -0,0 +1,115 @@
package com.fanruan.api.design.ui.component;
import com.fanruan.api.util.AssistKit;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.stable.Constants;
import com.fr.stable.StringUtils;
import javax.swing.*;
import javax.swing.plaf.basic.BasicComboBoxEditor;
import java.awt.*;
import java.awt.event.ActionListener;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Vector;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-28
* 下拉框
*/
public class UIComboBox<T> extends com.fr.design.gui.icombobox.UIComboBox {
public UIComboBox() {
super();
}
public UIComboBox(ComboBoxModel<T> model) {
super(model);
}
public UIComboBox(T[] items) {
super(items);
}
public UIComboBox(Vector<T> items) {
super(items);
}
/**
* 重新设置下拉选项
*
* @param list 下拉选项的集合
*/
public void refreshSelectableItems(List<T> list) {
T el = (T) getSelectedItem();
removeAllItems();
for (T t : list) {
addItem(t);
}
getModel().setSelectedItem(el);
}
public static class UIComboBoxEditor extends BasicComboBoxEditor {
protected UITextField textField;
private Object oldValue;
public UIComboBoxEditor() {
textField = new UITextField();
textField.setRectDirection(Constants.RIGHT);
}
@Override
public Component getEditorComponent() {
return textField;
}
@Override
public void setItem(Object anObject) {
if (anObject != null) {
textField.setText(anObject.toString());
oldValue = anObject;
} else {
textField.setText(StringUtils.EMPTY);
}
}
@Override
public Object getItem() {
Object newValue = textField.getText();
if (oldValue != null && !(oldValue instanceof String)) {
if (AssistKit.equals(newValue, oldValue.toString())) {
return oldValue;
} else {
Class cls = oldValue.getClass();
try {
Method method = cls.getMethod("valueOf", new Class[]{String.class});
newValue = method.invoke(oldValue, new Object[]{textField.getText()});
} catch (Exception ignore) {
}
}
}
return newValue;
}
@Override
public void selectAll() {
textField.selectAll();
textField.requestFocus();
}
@Override
public void addActionListener(ActionListener l) {
textField.addActionListener(l);
}
@Override
public void removeActionListener(ActionListener l) {
textField.removeActionListener(l);
}
}
}

4
src/main/java/com/fanruan/api/design/ui/component/UIDescriptionTextArea.java

@ -0,0 +1,4 @@
package com.fanruan.api.design.ui.component;
public class UIDescriptionTextArea extends com.fr.design.gui.itextarea.DescriptionTextArea{
}

14
src/main/java/com/fanruan/api/design/ui/component/UIDictionaryComboBox.java

@ -0,0 +1,14 @@
package com.fanruan.api.design.ui.component;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-28
* 带字典数据的下拉框显示值和实际值通过字典进行对应
*/
public class UIDictionaryComboBox<T> extends com.fr.design.gui.icombobox.UIDictionaryComboBox<T> {
public UIDictionaryComboBox(T[] keys, String[] values) {
super(keys, values);
}
}

24
src/main/java/com/fanruan/api/design/ui/component/UIIntNumberField.java

@ -1,5 +1,29 @@
package com.fanruan.api.design.ui.component; package com.fanruan.api.design.ui.component;
/**
* 整数控件该控件只能输入整数数字
*/
public class UIIntNumberField extends com.fr.design.gui.itextfield.UIIntNumberField { public class UIIntNumberField extends com.fr.design.gui.itextfield.UIIntNumberField {
public UIIntNumberField() {
}
/**
* 获取整数数值
*
* @return 整数值
*/
public int getInt() {
return (int) getValue();
}
/**
* 设置整数数值
*
* @param value 整数值
*/
public void setInt(int value) {
setValue(value);
}
} }

191
src/main/java/com/fanruan/api/design/ui/component/UILazyComboBox.java

@ -0,0 +1,191 @@
package com.fanruan.api.design.ui.component;
import com.fanruan.api.design.DesignKit;
import com.fanruan.api.log.LogKit;
import com.fanruan.api.util.StringKit;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import java.awt.*;
import java.util.concurrent.ExecutionException;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-28
* 懒加载下拉框点击下拉之后才开始加载数据
*/
public abstract class UILazyComboBox<T> extends UIComboBox<T> implements PopupMenuListener {
private static final int NUM = 80;
private static final String[] PENDING_CONTENT = new String[]{StringKit.EMPTY, DesignKit.i18nText("Fine-Design_Basic_Loading") + "..."};
/**
* 是否加载完成
*/
protected boolean loaded = false;
/**
* 初始化选项
*/
private Object initialSelected = null;
protected UILazyComboBox() {
super();
this.setEditor(new UILazyComboBox.FilterComboBoxEditor());
addPopupMenuListener(this);
}
public void setLoaded(boolean loaded) {
this.loaded = loaded;
}
/**
* 加载下拉框中的选项
*
* @return 下拉框中的选项
*/
public abstract Object[] load();
@Override
public void setSelectedItem(Object anObject) {
initialSelected = anObject;
if (loaded) {
super.setSelectedItem(anObject);
} else {
this.setModel(new DefaultComboBoxModel<>(new Object[]{anObject}));
super.setSelectedItem(anObject);
}
}
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
if (loaded) {
return;
}
DefaultComboBoxModel<String> loadingModel = new DefaultComboBoxModel<>(PENDING_CONTENT);
this.setModel(loadingModel);
new SwingWorker<Object[], Void>() {
@Override
protected Object[] doInBackground() {
return load();
}
@Override
public void done() {
try {
UILazyComboBox.this.loadList(get());
} catch (InterruptedException | ExecutionException exception) {
LogKit.debug(exception.getMessage());
}
UILazyComboBox.this.showPopup();
}
}.execute();
}
/**
* 加载下拉列表
*/
public void loadList() {
DefaultComboBoxModel<Object> model = new DefaultComboBoxModel<>(load());
model.setSelectedItem(initialSelected);
this.setModel(model);
this.selectedItemReminder = initialSelected;
loaded = true;
}
/**
* 加载下拉列表
*
* @param contents 下拉列表内容
*/
private void loadList(Object[] contents) {
DefaultComboBoxModel<Object> model = new DefaultComboBoxModel<>(contents);
model.setSelectedItem(initialSelected);
this.setModel(model);
this.selectedItemReminder = initialSelected;
loaded = true;
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
@Override
public Dimension getPreferredSize() {
Dimension dim = super.getPreferredSize();
dim.width = NUM;
return dim;
}
class FilterComboBoxEditor extends UIComboBoxEditor implements DocumentListener {
private Object item;
private volatile boolean filtering = false;
private volatile boolean setting = false;
public FilterComboBoxEditor() {
super();
textField.getDocument().addDocumentListener(this);
}
@Override
public void setItem(Object item) {
if (filtering) {
return;
}
this.item = item;
this.setting = true;
textField.setSetting(true);
String newText = (item == null) ? "" : item.toString();
textField.setText(newText);
textField.setSetting(false);
this.setting = false;
}
@Override
public Object getItem() {
return this.item;
}
@Override
public void insertUpdate(DocumentEvent e) {
handleChange();
}
@Override
public void removeUpdate(DocumentEvent e) {
handleChange();
}
@Override
public void changedUpdate(DocumentEvent e) {
handleChange();
}
void handleChange() {
if (setting) {
return;
}
filtering = true;
String xx = textField.getText();
UILazyComboBox.this.setSelectedItem(xx);
this.item = textField.getText();
setPopupVisible(true);
filtering = false;
}
}
}

45
src/main/java/com/fanruan/api/design/ui/component/UINumberField.java

@ -0,0 +1,45 @@
package com.fanruan.api.design.ui.component;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-28
* 数字文本框
*/
public class UINumberField extends com.fr.design.gui.itextfield.UINumberField {
/**
* 默认的数字文本框限制最大的输入整数位数为32位限制最大的小数输入位数为16位
*/
public UINumberField() {
super();
}
/**
* 默认的数字文本框限制最大的输入整数位数为32位限制最大的小数输入位数为16位
* @param columns 最大的文本输入列数
*/
public UINumberField(int columns) {
super(columns);
}
/**
* 限制整数和小数位数的数字文本框
* @param maxIntegerLength 最大整数位数
* @param maxDecimalLength 最大小数位数
*/
public UINumberField(int maxIntegerLength, int maxDecimalLength) {
super(maxIntegerLength, maxDecimalLength);
}
/**
* 限制整数和小数位数最大值以及最小值的数字文本框
* @param maxIntegerLength 最大整数位数
* @param maxDecimalLength 最大小数位数
* @param minValue 最小值
* @param maxValue 最大值
*/
public UINumberField(int maxIntegerLength, int maxDecimalLength, double minValue, double maxValue) {
super(maxIntegerLength, maxDecimalLength, minValue, maxValue);
}
}

19
src/main/java/com/fanruan/api/design/ui/component/UIPasswordField.java

@ -0,0 +1,19 @@
package com.fanruan.api.design.ui.component;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-28
* 密码输入控件
*/
public class UIPasswordField extends com.fr.design.gui.ipasswordfield.UIPassWordField {
public UIPasswordField() {
super();
}
public UIPasswordField(String text) {
super(text);
}
}

27
src/main/java/com/fanruan/api/design/ui/component/UIPlaceholderTextField.java

@ -0,0 +1,27 @@
package com.fanruan.api.design.ui.component;
import com.fr.design.gui.itextfield.PlaceholderTextField;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-28
* 带占位文本的文本编辑器当没有输入文本的时候会显示占位符
*/
public class UIPlaceholderTextField extends PlaceholderTextField {
public UIPlaceholderTextField() {
super();
}
public UIPlaceholderTextField(String placeHolder) {
super();
setPlaceholder(placeHolder);
}
public UIPlaceholderTextField(String text, String placeHolder) {
super(text);
setPlaceholder(placeHolder);
}
}

18
src/main/java/com/fanruan/api/design/ui/component/UISpinner.java

@ -0,0 +1,18 @@
package com.fanruan.api.design.ui.component;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-28
* 数字滚动控件
*/
public class UISpinner extends com.fr.design.gui.ispinner.UISpinner {
public UISpinner(double minValue, double maxValue, double delta) {
super(minValue, maxValue, delta);
}
public UISpinner(double minValue, double maxValue, double delta, double defaultValue) {
super(minValue, maxValue, delta, defaultValue);
}
}

35
src/main/java/com/fanruan/api/design/ui/component/UITable.java

@ -0,0 +1,35 @@
package com.fanruan.api.design.ui.component;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-28
* 表格控件
*/
public class UITable extends com.fr.design.gui.itable.UITable {
public UITable() {
super();
}
public UITable(int columnSize) {
super(columnSize);
}
/**
* @param values 一个列表里面装有字符串数组每个数组代表一行内容
*/
public UITable(@NotNull List<Object[]> values) {
super(values);
}
public UITable(int columnSize, boolean needAWTEventListener) {
super(columnSize, needAWTEventListener);
}
}

14
src/main/java/com/fanruan/api/design/ui/component/UIToolbar.java

@ -0,0 +1,14 @@
package com.fanruan.api.design.ui.component;
import com.fr.design.gui.itoolbar.UIToolBarUI;
public class UIToolbar extends com.fr.design.gui.itoolbar.UIToolbar{
public UIToolbar(){
}
public UIToolbar(int align) {
super(align);
}
}

35
src/main/java/com/fanruan/api/design/ui/component/code/SyntaxConstants.java

@ -0,0 +1,35 @@
package com.fanruan.api.design.ui.component.code;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-28
* 代码编辑器用到的常量
*/
public interface SyntaxConstants {
/**
* 普通文本编辑器
*/
String SYNTAX_STYLE_NONE = "text/plain";
/**
* java编辑器
*/
String SYNTAX_STYLE_JAVA = "text/java";
/**
* javascript编辑器
*/
String SYNTAX_STYLE_JAVASCRIPT = "text/javascript";
/**
* sql编辑器
*/
String SYNTAX_STYLE_SQL = "text/sql";
/**
* 公式编辑器
*/
String SYNTAX_STYLE_FORMULA = "text/formula";
}

37
src/main/java/com/fanruan/api/design/ui/component/code/UISyntaxTextArea.java

@ -0,0 +1,37 @@
package com.fanruan.api.design.ui.component.code;
import com.fr.design.gui.syntax.ui.rsyntaxtextarea.RSyntaxTextArea;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-28
* 代码编辑器支持javascriptsqljava公式和普通文本
* @see com.fanruan.api.design.ui.component.code.SyntaxConstants
* <p>
* UISyntaxTextArea contentTextArea = new UISyntaxTextArea();
* contentTextArea.setCloseCurlyBraces(true);
* contentTextArea.setLineWrap(true);
* contentTextArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT);
* contentTextArea.setCodeFoldingEnabled(true);
* contentTextArea.setAntiAliasingEnabled(true);
* </p>
*/
public class UISyntaxTextArea extends RSyntaxTextArea {
public UISyntaxTextArea() {
super();
}
public UISyntaxTextArea(String text) {
super(text);
}
public UISyntaxTextArea(int rows, int cols) {
super(rows, cols);
}
public UISyntaxTextArea(String text, int rows, int cols) {
super(text, rows, cols);
}
}

30
src/main/java/com/fanruan/api/design/ui/component/code/UISyntaxTextScrollPane.java

@ -0,0 +1,30 @@
package com.fanruan.api.design.ui.component.code;
import com.fr.design.gui.syntax.ui.rtextarea.RTextScrollPane;
import java.awt.*;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-28
* 可滚动的代码编辑器容器
*/
public class UISyntaxTextScrollPane extends RTextScrollPane {
public UISyntaxTextScrollPane() {
}
public UISyntaxTextScrollPane(Component component) {
super(component);
}
public UISyntaxTextScrollPane(Component component, boolean lineNumbers) {
super(component, lineNumbers);
}
public UISyntaxTextScrollPane(Component component, boolean lineNumbers, Color lineNumberColor) {
super(component, lineNumbers, lineNumberColor);
}
}

45
src/main/java/com/fanruan/api/design/ui/component/formula/UIFormulaTextField.java

@ -0,0 +1,45 @@
package com.fanruan.api.design.ui.component.formula;
import com.fr.design.formula.TinyFormulaPane;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-28
* 带公式选择器的公式输入文本框
*/
public class UIFormulaTextField extends TinyFormulaPane {
public UIFormulaTextField() {
super();
}
public UIFormulaTextField(String text) {
super();
setText(text);
}
/**
* 设置公式文本框的内容
* @param text 公式文本
*/
public void setText(String text) {
populateBean(text);
}
/**
* 获取公式文本框的内容
* @return 公式内容
*/
public String getText() {
return updateBean();
}
/**
* 公式窗口点击确定后的事件接口该方法一般用于重载
*/
public void okEvent() {
}
}

21
src/main/java/com/fanruan/api/design/ui/component/table/UITableEditorPane.java

@ -0,0 +1,21 @@
package com.fanruan.api.design.ui.component.table;
import com.fanruan.api.design.ui.component.table.model.UITableModelAdapter;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-28
* 可增改的表格控件
*/
public class UITableEditorPane<T> extends com.fr.design.gui.itableeditorpane.UITableEditorPane<T> {
public UITableEditorPane(UITableModelAdapter<T> adapter) {
super(adapter);
}
public UITableEditorPane(UITableModelAdapter<T> adapter, String leftLabelName) {
super(adapter, leftLabelName);
}
}

3
src/main/java/com/fanruan/api/design/ui/component/table/action/UITableEditAction.java

@ -2,7 +2,8 @@ package com.fanruan.api.design.ui.component.table.action;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
public class UITableEditAction extends com.fr.design.gui.itableeditorpane.UITableEditAction{ public class UITableEditAction extends com.fr.design.gui.itableeditorpane.UITableEditAction {
@Override @Override
public void checkEnabled() { public void checkEnabled() {
} }

334
src/main/java/com/fanruan/api/design/ui/component/table/model/ParameterTableModel.java

@ -1,28 +1,350 @@
package com.fanruan.api.design.ui.component.table.model; package com.fanruan.api.design.ui.component.table.model;
import com.fanruan.api.cal.ParameterKit;
import com.fanruan.api.design.DesignKit;
import com.fanruan.api.design.ui.component.UILabel;
import com.fanruan.api.design.ui.component.UITextField;
import com.fanruan.api.design.ui.component.table.action.UITableEditAction;
import com.fanruan.api.design.ui.editor.ValueEditorPane; import com.fanruan.api.design.ui.editor.ValueEditorPane;
import com.fanruan.api.design.ui.editor.ValueEditors;
import com.fanruan.api.log.LogKit;
import com.fanruan.api.util.IOKit;
import com.fanruan.api.util.StringKit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.stable.ParameterProvider;
import javax.swing.*;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import java.awt.*; import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.Collections;
/** /**
* 表格模型 * 编辑参数的表格模型通常来说就是两列参数名和参数值
*/ */
public class ParameterTableModel extends com.fr.design.gui.itableeditorpane.ParameterTableModel { public class ParameterTableModel extends UITableModelAdapter<ParameterProvider> {
public static final int NO_CHART_USE = 0;
public static final int CHART_NORMAL_USE = 1;
public static final int FORM_NORMAL_USE = -1;
private static final long serialVersionUID = 1L;
protected Component component = null;
public ParameterTableModel() { public ParameterTableModel() {
super(); this(NO_CHART_USE);
} }
public ParameterTableModel(int paraUseType) { public ParameterTableModel(int paraUseType) {
super(paraUseType); super(new String[]{DesignKit.i18nText("Fine-Design_Basic_Parameter"), DesignKit.i18nText("Fine-Design_Basic_Value")});
this.setColumnClass(new Class[]{ParameterEditor.class, ParameterValueEditor.class});
this.setDefaultEditor(ParameterValueEditor.class, new ParameterValueEditor(paraUseType));
this.setDefaultEditor(ParameterEditor.class, new ParameterEditor());
this.setDefaultRenderer(ParameterValueEditor.class, new ParameterValueRenderer(paraUseType));
} }
public ParameterTableModel(int paraUseType, Component component) { public ParameterTableModel(int paraUseType, Component component) {
super(paraUseType, component); super(new String[]{DesignKit.i18nText("Fine-Design_Basic_Parameter"), DesignKit.i18nText("Fine-Design_Basic_Value")});
this.setColumnClass(new Class[]{ParameterEditor.class, ParameterValueEditor.class});
this.setDefaultEditor(ParameterValueEditor.class, new ParameterValueEditor(paraUseType));
this.setDefaultEditor(ParameterEditor.class, new ParameterEditor());
this.setDefaultRenderer(ParameterValueEditor.class, new ParameterValueRenderer(paraUseType));
this.component = component;
} }
public ParameterTableModel(ValueEditorPane valueEditorPane, ValueEditorPane valueRenderPane, Component component) { public ParameterTableModel(ValueEditorPane valueEditorPane, ValueEditorPane valueRenderPane, Component component) {
super(valueEditorPane, valueRenderPane, component); super(new String[]{DesignKit.i18nText("Fine-Design_Basic_Parameter"), DesignKit.i18nText("Fine-Design_Basic_Value")});
this.setColumnClass(new Class[]{ParameterEditor.class, ParameterValueEditor.class});
this.setDefaultEditor(ParameterValueEditor.class, new ParameterValueEditor(valueEditorPane));
this.setDefaultEditor(ParameterEditor.class, new ParameterEditor());
this.setDefaultRenderer(ParameterValueEditor.class, new ParameterValueRenderer(valueRenderPane));
this.component = component;
}
/**
* 单元格是否可编辑
*
* @param row
* @param col
* @return 是否可以编辑
*/
public boolean isCellEditable(int row, int col) {
if (col == 1) {
return this.getList().get(row) != null && StringKit.isNotEmpty(this.getList().get(row).getName());
}
return true;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
ParameterProvider para = this.getList().get(rowIndex);
switch (columnIndex) {
case 0:
return para.getName();
case 1:
return para.getValue();
}
return null;
}
/**
* 生成工具栏上的一系列动作按钮
*
* @return 返回table上的action数组.
*/
@Override
public UITableEditAction[] createAction() {
return new UITableEditAction[]{new AddParameterAction(), new DeleteAction(), new MoveUpAction(), new MoveDownAction()};
} }
protected class AddParameterAction extends AddTableRowAction {
public AddParameterAction() {
super();
}
@Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
addParameter();
}
}
private void addParameter() {
ParameterProvider para = ParameterKit.newParameter();
addRow(para);
fireTableDataChanged();
table.getSelectionModel().setSelectionInterval(table.getRowCount() - 1, table.getRowCount() - 1);
}
protected class DeleteAction extends UITableEditAction {
private Component component = null;
public DeleteAction() {
this.setName(DesignKit.i18nText("Fine-Design_Report_Delete"));
this.setSmallIcon(IOKit.readIcon("/com/fr/base/images/cell/control/remove.png"));
}
public DeleteAction(Component component) {
this.setName(DesignKit.i18nText("Fine-Design_Report_Delete"));
this.setSmallIcon(IOKit.readIcon("/com/fr/base/images/cell/control/remove.png"));
this.component = component;
}
@Override
public void actionPerformed(ActionEvent e) {
int[] selectedRow = table.getSelectedRows();
if (isMultiSelected()) {
JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), DesignKit.i18nText("Fine-Design_Basic_Multiple_Select_Warn_Text"));
return;
}
if (table.getCellEditor() != null) {
try {
table.getCellEditor().stopCellEditing();
} catch (Exception ee) {
LogKit.error(ee.getMessage(), ee);
}
}
if (getRowCount() < 1) {
return;
}
if (component == null) {
component = DesignerContext.getDesignerFrame();
}
int val = JOptionPane.showConfirmDialog(component,
DesignKit.i18nText("Fine-Design_Basic_Utils_Are_You_Sure_To_Remove_The_Selected_Item") + "?", DesignKit.i18nText("Fine-Design_Basic_Remove"),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
if (val != JOptionPane.OK_OPTION) {
return;
}
for (int i = 0; i < selectedRow.length; i++) {
if (selectedRow[i] - i < 0) {
continue;
}
removeRow(selectedRow[i] - i);
}
fireTableDataChanged();
int selection = selectedRow[0] > table.getRowCount() ? table.getRowCount() - 1
: (selectedRow[0] > 1 ? selectedRow[0] - 1 : 0);
table.getSelectionModel().setSelectionInterval(selection, selection);
}
private boolean isMultiSelected() {
int[] selectedRow = table.getSelectedRows();
return (selectedRow.length == 1 && (selectedRow[0] > table.getRowCount() - 1 || selectedRow[0] < 0)) || selectedRow.length == 0;
}
@Override
public void checkEnabled() {
setEnabled(!isMultiSelected());
}
}
protected class MoveUpAction extends UITableEditAction {
public MoveUpAction() {
this.setName(DesignKit.i18nText("Fine-Design_Basic_Utils_Move_Up"));
this.setSmallIcon(IOKit.readIcon("/com/fr/design/images/control/up.png"));
}
@Override
public void actionPerformed(ActionEvent e) {
int selectedRow = table.getSelectedRow();
stopCellEditing();
if (getList().size() < 2 || selectedRow == 0) {
return;
}
Collections.swap(getList(), selectedRow, selectedRow - 1);
fireTableDataChanged();
table.getSelectionModel().setSelectionInterval(selectedRow - 1, selectedRow - 1);
}
@Override
public void checkEnabled() {
}
}
protected class MoveDownAction extends UITableEditAction {
public MoveDownAction() {
this.setName(DesignKit.i18nText("Fine-Design_Basic_Utils_Move_Down"));
this.setSmallIcon(IOKit.readIcon("/com/fr/design/images/control/down.png"));
}
@Override
public void actionPerformed(ActionEvent e) {
int selectedRow = table.getSelectedRow();
stopCellEditing();
if (getList().size() < 2 || selectedRow == getRowCount() - 1) {
return;
}
Collections.swap(getList(), selectedRow, selectedRow + 1);
fireTableDataChanged();
table.getSelectionModel().setSelectionInterval(selectedRow + 1, selectedRow + 1);
}
@Override
public void checkEnabled() {
}
}
public class ParameterEditor extends AbstractCellEditor implements TableCellEditor {
private UITextField textField;
public ParameterEditor() {
textField = new UITextField();
this.addCellEditorListener(new CellEditorListener() {
@Override
public void editingCanceled(ChangeEvent e) {
}
@Override
public void editingStopped(ChangeEvent e) {
if (table.getSelectedRow() == -1) {
return;
}
ParameterProvider para = getList().get(table.getSelectedRow());
String value = StringKit.trimToNull(textField.getText());
para.setName(value);
fireTableDataChanged();
}
});
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
textField.setText((String) value);
return textField;
}
@Override
public Object getCellEditorValue() {
return textField.getText();
}
}
private class ParameterValueEditor extends AbstractCellEditor implements TableCellEditor {
private static final long serialVersionUID = 1L;
private ValueEditorPane editor;
public ParameterValueEditor(int paraUseType) {
this(ValueEditors.createValueEditorPaneWithUseType(paraUseType));
}
public ParameterValueEditor(ValueEditorPane valueEditorPane) {
editor = valueEditorPane;
this.addCellEditorListener(new CellEditorListener() {
@Override
public void editingCanceled(ChangeEvent e) {
}
@Override
public void editingStopped(ChangeEvent e) {
if (table.getSelectedRow() == -1) {
return;
}
ParameterProvider para = getList().get(table.getSelectedRow());
para.setValue(getCellEditorValue());
fireTableDataChanged();
}
});
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
editor.populate(value == null ? StringKit.EMPTY : value);
return editor;
}
@Override
public Object getCellEditorValue() {
return editor.update();
}
}
private class ParameterValueRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 1L;
private ValueEditorPane editor;
private UILabel disableLabel;
public ParameterValueRenderer(int paraUseType) {
this(ValueEditors.createValueEditorPaneWithUseType(paraUseType));
}
public ParameterValueRenderer(ValueEditorPane valueEditorPane) {
disableLabel = new UILabel(DesignKit.i18nText("Fine-Design_Basic_Set_Paramete_Name"));
disableLabel.setForeground(Color.pink);
disableLabel.setHorizontalAlignment(SwingConstants.CENTER);
editor = valueEditorPane;
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (table.isCellEditable(row, column)) {
if (value == null) {
editor.populate(StringKit.EMPTY);
} else {
editor.populate(value);
}
return editor;
} else {
return disableLabel;
}
}
}
} }

62
src/main/java/com/fanruan/api/design/ui/component/table/model/UITableModelAdapter.java

@ -0,0 +1,62 @@
package com.fanruan.api.design.ui.component.table.model;
import com.fanruan.api.design.DesignKit;
import com.fanruan.api.design.ui.component.table.action.UITableEditAction;
import com.fanruan.api.util.IOKit;
import com.fr.design.mainframe.DesignerContext;
import javax.swing.*;
import java.awt.event.ActionEvent;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-28
*
*/
public abstract class UITableModelAdapter<T> extends com.fr.design.gui.itableeditorpane.UITableModelAdapter<T> {
protected UITableModelAdapter(String[] strings) {
super(strings);
}
public abstract UITableEditAction[] createAction();
protected abstract class AddTableRowAction extends UITableEditAction {
public AddTableRowAction() {
this.setName(DesignKit.i18nText("Fine-Design_Report_Insert"));
this.setSmallIcon(IOKit.readIcon("/com/fr/base/images/cell/control/add.png"));
}
@Override
public void actionPerformed(ActionEvent e) {
stopCellEditing();
}
public void checkEnabled() {
}
}
protected abstract class EditAction extends UITableEditAction {
public EditAction() {
this.setName(DesignKit.i18nText("Fine-Design_Report_Edit"));
this.setSmallIcon(IOKit.readIcon("/com/fr/design/images/control/edit.png"));
}
@Override
public void actionPerformed(ActionEvent e) {
final int selectedRow = table.getSelectedRow();
if (selectedRow > table.getRowCount() - 1 || selectedRow < 0) {
JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), DesignKit.i18nText("Fine-Design_Basic_No-Alternatives"));
return;
}
stopCellEditing();
}
}
}

4
src/main/java/com/fanruan/api/design/ui/container/BasicBeanPane.java

@ -0,0 +1,4 @@
package com.fanruan.api.design.ui.container;
public abstract class BasicBeanPane extends com.fr.design.beans.BasicBeanPane{
}

36
src/main/java/com/fanruan/api/design/ui/container/BasicDialog.java

@ -0,0 +1,36 @@
package com.fanruan.api.design.ui.container;
import com.fanruan.api.design.ui.container.BasicPane;
import java.awt.*;
public class BasicDialog extends com.fr.design.dialog.BasicDialog{
public BasicDialog(Dialog parent){
super(parent);
}
public BasicDialog(Dialog parent, BasicPane pane){
super(parent, pane);
}
public BasicDialog(Dialog parent, BasicPane pane, boolean isNeedButton){
super(parent, pane, isNeedButton);
}
public BasicDialog(Frame parent){
super(parent);
}
public BasicDialog(Frame parent, BasicPane pane){
super(parent, pane);
}
public BasicDialog(Frame parent, BasicPane pane, boolean isNedButtonPane){
super(parent, pane, isNedButtonPane);
}
@Override
public void checkValid(){
}
}

8
src/main/java/com/fanruan/api/design/ui/container/DialogActionAdapter.java

@ -0,0 +1,8 @@
package com.fanruan.api.design.ui.container;
import com.fr.design.layout.FRGUIPaneFactory;
public class DialogActionAdapter extends com.fr.design.dialog.DialogActionAdapter{
public DialogActionAdapter(){
}
}

16
src/main/java/com/fanruan/api/design/ui/container/UIScrollPane.java

@ -0,0 +1,16 @@
package com.fanruan.api.design.ui.container;
import java.awt.*;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-28
* 可滚动容器
*/
public class UIScrollPane extends com.fr.design.gui.icontainer.UIScrollPane {
public UIScrollPane(Component component) {
super(component);
}
}

445
src/main/java/com/fanruan/api/design/ui/editor/ValueEditors.java

@ -0,0 +1,445 @@
package com.fanruan.api.design.ui.editor;
import com.fanruan.api.design.DesignKit;
import com.fanruan.api.design.ui.component.table.model.ParameterTableModel;
import com.fanruan.api.util.StringKit;
import com.fr.base.BaseFormula;
import com.fr.design.editor.editor.BooleanEditor;
import com.fr.design.editor.editor.ColumnRowEditor;
import com.fr.design.editor.editor.ColumnRowGroupEditor;
import com.fr.design.editor.editor.ColumnSelectedEditor;
import com.fr.design.editor.editor.ConstantsEditor;
import com.fr.design.editor.editor.CursorEditor;
import com.fr.design.editor.editor.DateEditor;
import com.fr.design.editor.editor.DoubleEditor;
import com.fr.design.editor.editor.Editor;
import com.fr.design.editor.editor.FormulaEditor;
import com.fr.design.editor.editor.IntegerEditor;
import com.fr.design.editor.editor.NoneEditor;
import com.fr.design.editor.editor.ParameterEditor;
import com.fr.design.editor.editor.SpinnerIntegerEditor;
import com.fr.design.editor.editor.TextEditor;
import com.fr.design.editor.editor.WidgetNameEditor;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-28
* 工厂类创建多种组合编辑器
*/
public class ValueEditors {
/**
* 创建带编辑器的ValueEditorPane
*
* @param editors 自定义的编辑器
* @return 返回pane
*/
public static ValueEditorPane createValueEditorPane(Editor<?>[] editors) {
return createValueEditorPane(editors, StringKit.EMPTY, StringKit.EMPTY);
}
/**
* 创建编辑器 名称 弹出的ValueEditorPane
*
* @param editors 编辑器
* @param popupName 弹出的名字
* @param textEditorValue
* @return 返回pane
*/
public static ValueEditorPane createValueEditorPane(Editor<?>[] editors, String popupName, String textEditorValue) {
return new ValueEditorPane(editors, popupName, textEditorValue);
}
/**
* 创建编辑器 名称 弹出的ValueEditorPane
*
* @param editors 编辑器
* @param popupName 弹出的名字
* @param textEditorValue
* @param editor_center_width 编辑器主体的宽度
* @return 返回pane
*/
public static ValueEditorPane createValueEditorPane(Editor<?>[] editors, String popupName, String textEditorValue, int editor_center_width) {
return new ValueEditorPane(editors, popupName, textEditorValue, editor_center_width);
}
/**
* 创建基本的值编辑器面板
*
* @return 返回值编辑器面板
*/
public static ValueEditorPane createBasicValueEditorPane() {
return createValueEditorPane(basicEditors(), StringKit.EMPTY, StringKit.EMPTY);
}
/**
* 创建公式编辑器面板
*
* @return 返回公式编辑器面板
*/
public static ValueEditorPane createFormulaValueEditorPane() {
return createValueEditorPane(new Editor[]{new FormulaEditor(DesignKit.i18nText("Fine-Design_Basic_Parameter_Formula"))},
StringKit.EMPTY, StringKit.EMPTY);
}
/**
* 创建基本的值编辑器面板
*
* @param editorCenterWidth 指定值编辑器的主体宽度
* @return 返回值编辑器面板
*/
public static ValueEditorPane createBasicValueEditorPane(int editorCenterWidth) {
return createValueEditorPane(basicEditors(), StringKit.EMPTY, StringKit.EMPTY, editorCenterWidth);
}
/**
* Process用的editorPane
*
* @return 值编辑器面板
*/
public static ValueEditorPane createFormEditorPane() {
return createValueEditorPane(formEditors(), StringKit.EMPTY, StringKit.EMPTY);
}
/**
* URL使用的ValueEditorPane
*
* @param popupName 弹出的名字
* @param textEditorValue 编辑器值
* @return 值编辑器返回
*/
public static ValueEditorPane createURLValueEditorPane(String popupName, String textEditorValue) {
return createValueEditorPane(URLEditors(popupName, textEditorValue), StringKit.EMPTY, StringKit.EMPTY);
}
/**
* 创建日期的ValueEditorPane
*
* @param popupName 名字
* @param textEditorValue
* @return 值编辑器面板
*/
public static ValueEditorPane createDateValueEditorPane(String popupName, String textEditorValue) {
return createValueEditorPane(dateEditors(popupName, textEditorValue), StringKit.EMPTY, StringKit.EMPTY);
}
/**
* 带有所有编辑器的ValueEditorPane
*
* @return 值编辑器面板
*/
public static ValueEditorPane createAllValueEditorPane() {
return createValueEditorPane(allEditors(), StringKit.EMPTY, StringKit.EMPTY);
}
/**
* 创建不带公式面板的pane
*
* @return 编辑器面板
*/
public static ValueEditorPane createBasicEditorWithoutFormulaPane() {
return createValueEditorPane(basicEditorsWithoutFormula(), StringKit.EMPTY, StringKit.EMPTY);
}
/**
* 创建日期编辑器
*
* @return 值编辑器
*/
public static ValueEditorPane createDateValueEditorPane() {
return createValueEditorPane(dateEditors(), StringKit.EMPTY, StringKit.EMPTY);
}
/**
* 根据参数paraUseType 创建编辑器类型.
*
* @param paraUseType 参数类型
* @return 值编辑器
*/
public static ValueEditorPane createValueEditorPaneWithUseType(int paraUseType) {
return createValueEditorPaneWithUseType(paraUseType, null);
}
public static ValueEditorPane createValueEditorPaneWithUseType(int paraUseType, Map<String, BaseFormula> hyperLinkEditorMap) {
if (paraUseType == ParameterTableModel.NO_CHART_USE) {
return createBasicValueEditorPane();
} else if (paraUseType == ParameterTableModel.FORM_NORMAL_USE) {
return createFormEditorPane();
} else {
return createChartHotValueEditorPane(hyperLinkEditorMap);
}
}
/**
* 图表用的参数编辑器的ValueEditorPane
*
* @param hyperLinkEditorMap 超链下拉参数类型
* @return 值编辑器
*/
public static ValueEditorPane createChartHotValueEditorPane(Map<String, BaseFormula> hyperLinkEditorMap) {
return createValueEditorPane(chartHotEditors(hyperLinkEditorMap), StringKit.EMPTY, StringKit.EMPTY);
}
/**
* 基础的一些ValueEditorPane所用到的Editors
*
* @return 值编辑器
*/
public static Editor<?>[] basicEditors() {
FormulaEditor formulaEditor = new FormulaEditor(DesignKit.i18nText("Fine-Design_Basic_Parameter_Formula"));
return new Editor[]{
new TextEditor(),
new SpinnerIntegerEditor(),
new DoubleEditor(),
new DateEditor(true, DesignKit.i18nText("Fine-Design_Basic_Date")),
new BooleanEditor(),
formulaEditor
};
}
/**
* 表单的一些编辑器.
*
* @return 值编辑器
*/
public static Editor<?>[] formEditors() {
FormulaEditor formulaEditor = new FormulaEditor(DesignKit.i18nText("Fine-Design_Basic_Parameter_Formula"));
return new Editor[]{
new TextEditor(),
new IntegerEditor(),
new DoubleEditor(),
new DateEditor(true, DesignKit.i18nText("Fine-Design_Basic_Date")),
new BooleanEditor(),
formulaEditor,
new WidgetNameEditor(DesignKit.i18nText("Fine-Design_Report_Widget"))
};
}
/**
* 扩展单元格的一些编辑器
*
* @return 值编辑器
*/
public static Editor<?>[] extendedEditors() {
FormulaEditor formulaEditor = new FormulaEditor(DesignKit.i18nText("Fine-Design_Basic_Parameter_Formula"));
return new Editor[]{
new TextEditor(),
new IntegerEditor(),
new DoubleEditor(),
new DateEditor(true, DesignKit.i18nText("Fine-Design_Basic_Date")),
new BooleanEditor(),
formulaEditor,
new ParameterEditor(),
new ColumnRowEditor(DesignKit.i18nText("Fine-Design_Basic_Cell"))
};
}
/**
* 带单元格组的编辑器
*
* @return 值编辑器
*/
public static Editor<?>[] extendedCellGroupEditors() {
FormulaEditor formulaEditor = new FormulaEditor(DesignKit.i18nText("Fine-Design_Basic_Parameter_Formula"));
return new Editor[]{
new TextEditor(),
new IntegerEditor(),
new DoubleEditor(),
new DateEditor(true, DesignKit.i18nText("Fine-Design_Basic_Date")),
new BooleanEditor(),
formulaEditor,
new ParameterEditor(),
new ColumnRowEditor(DesignKit.i18nText("Fine-Design_Basic_Cell")),
new ColumnRowGroupEditor(DesignKit.i18nText("Fine-Design_Basic_Cell_Group"))
};
}
/**
* 只有单元格和单元格组的编辑器
*
* @return 编辑器b
*/
public static Editor<?>[] cellGroupEditor() {
return new Editor[]{
new ColumnRowEditor(DesignKit.i18nText("Fine-Design_Basic_Cell")),
new ColumnRowGroupEditor(DesignKit.i18nText("Fine-Design_Basic_Cell_Group"))
};
}
/**
* URL的一些编辑器.
*
* @param popupName 名字
* @param textEditorValue
* @return 值编辑器
*/
public static Editor<?>[] URLEditors(String popupName, String textEditorValue) {
return new Editor[]{
new NoneEditor(textEditorValue, StringKit.isEmpty(popupName) ? DesignKit.i18nText("Fine-Design_Basic_None") : popupName),
new TextEditor()
};
}
/**
* 日期类型的一些编辑器
*
* @param popupName 名字
* @param textEditorValue
* @return 值编辑器
*/
public static Editor<?>[] dateEditors(String popupName, String textEditorValue) {
return new Editor[]{
new NoneEditor(textEditorValue, StringKit.isEmpty(popupName) ? DesignKit.i18nText("Fine-Design_Basic_None") : popupName),
new DateEditor(true, DesignKit.i18nText("Fine-Design_Basic_Date")),
new FormulaEditor(DesignKit.i18nText("Fine-Design_Basic_Parameter_Formula"))
};
}
/**
* 所有类型的编辑器
*
* @return 值编辑器
*/
public static Editor<?>[] allEditors() {
FormulaEditor formulaEditor = new FormulaEditor(DesignKit.i18nText("Fine-Design_Basic_Parameter_Formula"));
return new Editor[]{
new TextEditor(),
new IntegerEditor(),
new DoubleEditor(),
new DateEditor(true, DesignKit.i18nText("Fine-Design_Basic_Date")),
new BooleanEditor(),
formulaEditor,
new ParameterEditor(),
new ColumnRowEditor(DesignKit.i18nText("Fine-Design_Basic_Cell")),
new ColumnSelectedEditor(),
};
}
/**
* 不带公式编辑器
*
* @return 编辑器不带公式
*/
public static Editor<?>[] basicEditorsWithoutFormula() {
return new Editor[]{
new TextEditor(),
new IntegerEditor(),
new DoubleEditor(),
new DateEditor(true, DesignKit.i18nText("Fine-Design_Basic_Date")),
new BooleanEditor(),
};
}
/**
* noCRnoColumn编辑器
*
* @return 编辑器
*/
public static Editor<?>[] noCRnoColumnEditors() {
FormulaEditor formulaEditor = new FormulaEditor(DesignKit.i18nText("Fine-Design_Basic_Parameter_Formula"));
return new Editor[]{
new TextEditor(),
new IntegerEditor(),
new DoubleEditor(),
new DateEditor(true, DesignKit.i18nText("Fine-Design_Basic_Date")),
new BooleanEditor(),
formulaEditor,
new ParameterEditor(),
};
}
/**
* 数值编辑器
*
* @return 编辑器
*/
public static Editor<?>[] numberEditors() {
FormulaEditor formulaEditor = new FormulaEditor(DesignKit.i18nText("Fine-Design_Basic_Parameter_Formula"));
return new Editor[]{
new IntegerEditor(),
new DoubleEditor(),
formulaEditor,
new ParameterEditor(),
};
}
/**
* 日期编辑器
*
* @return 编辑器
*/
public static Editor<?>[] dateEditors() {
FormulaEditor formulaEditor = new FormulaEditor(DesignKit.i18nText("Fine-Design_Basic_Parameter_Formula"));
return new Editor[]{
new DateEditor(true, DesignKit.i18nText("Fine-Design_Basic_Date")),
formulaEditor,
new ParameterEditor(),
};
}
/**
* 存储的一些编辑器
*
* @return 存储过程的编辑器
*/
public static Editor<?>[] StoreProcedureEditors() {
FormulaEditor formulaEditor = new FormulaEditor(DesignKit.i18nText("Fine-Design_Basic_Parameter_Formula"));
formulaEditor.setEnabled(true);
return new Editor[]{
new CursorEditor(),
new TextEditor(),
new IntegerEditor(),
new DoubleEditor(),
new DateEditor(true, DesignKit.i18nText("Fine-Design_Basic_Date")),
new BooleanEditor(),
formulaEditor
};
}
/**
* 图表热点的一些编辑器
*
* @return 值编辑器
*/
public static Editor[] chartHotEditors(Map<String, BaseFormula> hyperLinkEditorMap) {
List<Editor> list = createEditors4Chart(hyperLinkEditorMap);
list.add(new TextEditor());
list.add(new IntegerEditor());
list.add(new DoubleEditor());
list.add(new DateEditor(true, DesignKit.i18nText("Fine-Design_Basic_Date")));
list.add(new BooleanEditor());
FormulaEditor formulaEditor = new FormulaEditor(DesignKit.i18nText("Fine-Design_Basic_Parameter_Formula"));
formulaEditor.setEnabled(true);
list.add(formulaEditor);
return list.toArray(new Editor[0]);
}
/**
* 为图表创建编辑器.
*
* @return 值编辑器
*/
private static List<Editor> createEditors4Chart(Map<String, BaseFormula> hyperLinkEditorMap) {
List<Editor> lists = new ArrayList<>();
if (hyperLinkEditorMap == null) {
return lists;
}
Iterator<Map.Entry<String, BaseFormula>> entries = hyperLinkEditorMap.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<String, BaseFormula> entry = entries.next();
ConstantsEditor editor = new ConstantsEditor(entry.getKey(), entry.getValue());
editor.setEnabled(false);
lists.add(editor);
}
return lists;
}
}

31
src/main/java/com/fanruan/api/design/util/I18nDesignKit.java

@ -1,31 +0,0 @@
package com.fanruan.api.design.util;
import com.fr.design.i18n.Toolkit;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-28
* 设计器国际化工具类设计器相关类的国际化都需要调用这个类才行
*/
public class I18nDesignKit {
/**
* 文本国际化
* @param key 国际化键
* @return 国际化后的值
*/
public String i18nText(String key) {
return Toolkit.i18nText(key);
}
/**
* 带参数的文本国际化
* @param key 国际化键
* @param args 参数
* @return 国际化后的值
*/
public String i18nText(String key, Object... args) {
return Toolkit.i18nText(key, args);
}
}

9
src/main/java/com/fanruan/api/design/work/ConnectionComboBoxPanel.java

@ -0,0 +1,9 @@
package com.fanruan.api.design.work;
import com.fr.data.impl.Connection;
public class ConnectionComboBoxPanel extends com.fr.design.data.datapane.connect.ConnectionComboBoxPanel{
public ConnectionComboBoxPanel(Class<? extends Connection> cls) {
super(cls);
}
}

7
src/main/java/com/fanruan/api/design/work/DatabaseConnectionPane.java

@ -0,0 +1,7 @@
package com.fanruan.api.design.work;
import javax.swing.*;
public abstract class DatabaseConnectionPane extends com.fr.design.data.datapane.connect.DatabaseConnectionPane{
}

4
src/main/java/com/fanruan/api/err/UtilEvalError.java

@ -0,0 +1,4 @@
package com.fanruan.api.err;
public class UtilEvalError extends com.fr.stable.UtilEvalError{
}

48
src/main/java/com/fanruan/api/macro/EncodeConstants.java

@ -0,0 +1,48 @@
package com.fanruan.api.macro;
/**
* 编码常量
*/
public interface EncodeConstants {
/**
* utf-8编码
*/
String ENCODING_UTF_8 = com.fr.stable.EncodeConstants.ENCODING_UTF_8;
/**
* gbk编码
*/
String ENCODING_GBK = com.fr.stable.EncodeConstants.ENCODING_GBK;
/**
* big5编码一般用于繁体中文
*/
String ENCODING_BIG5 = com.fr.stable.EncodeConstants.ENCODING_BIG5;
/**
* ios-8859-1编码
*/
String ENCODING_ISO_8859_1 = com.fr.stable.EncodeConstants.ENCODING_ISO_8859_1;
/**
* utf16编码
*/
String ENCODING_UTF_16 = com.fr.stable.EncodeConstants.ENCODING_UTF_16;
/**
* euc-jp编码
*/
String ENCODING_EUC_JP = com.fr.stable.EncodeConstants.ENCODING_EUC_JP;
/**
* euc-kr编码
*/
String ENCODING_EUC_KR = com.fr.stable.EncodeConstants.ENCODING_EUC_KR;
/**
* cp850编码
*/
String ENCODING_CP850 = com.fr.stable.EncodeConstants.ENCODING_CP850;
}

677
src/main/java/com/fanruan/api/net/http/HttpKit.java

@ -0,0 +1,677 @@
package com.fanruan.api.net.http;
import com.fanruan.api.macro.EncodeConstants;
import com.fanruan.api.log.LogKit;
import com.fanruan.api.net.http.rs.BaseHttpResponseHandle;
import com.fanruan.api.net.http.rs.HttpRequest;
import com.fanruan.api.net.http.rs.HttpRequestType;
import com.fanruan.api.net.http.rs.HttpResponseType;
import com.fanruan.api.net.http.rs.StreamResponseHandle;
import com.fanruan.api.net.http.rs.TextResponseHandle;
import com.fanruan.api.net.http.rs.UploadResponseHandle;
import com.fr.third.guava.collect.Maps;
import com.fr.third.org.apache.http.HttpEntity;
import com.fr.third.org.apache.http.HttpEntityEnclosingRequest;
import com.fr.third.org.apache.http.HttpHost;
import com.fr.third.org.apache.http.NameValuePair;
import com.fr.third.org.apache.http.NoHttpResponseException;
import com.fr.third.org.apache.http.client.HttpRequestRetryHandler;
import com.fr.third.org.apache.http.client.config.RequestConfig;
import com.fr.third.org.apache.http.client.entity.UrlEncodedFormEntity;
import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse;
import com.fr.third.org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import com.fr.third.org.apache.http.client.methods.HttpRequestBase;
import com.fr.third.org.apache.http.client.protocol.HttpClientContext;
import com.fr.third.org.apache.http.client.utils.URIBuilder;
import com.fr.third.org.apache.http.config.Registry;
import com.fr.third.org.apache.http.config.RegistryBuilder;
import com.fr.third.org.apache.http.conn.routing.HttpRoute;
import com.fr.third.org.apache.http.conn.socket.ConnectionSocketFactory;
import com.fr.third.org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import com.fr.third.org.apache.http.conn.socket.PlainConnectionSocketFactory;
import com.fr.third.org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import com.fr.third.org.apache.http.entity.FileEntity;
import com.fr.third.org.apache.http.entity.mime.HttpMultipartMode;
import com.fr.third.org.apache.http.entity.mime.MultipartEntityBuilder;
import com.fr.third.org.apache.http.impl.client.CloseableHttpClient;
import com.fr.third.org.apache.http.impl.client.HttpClients;
import com.fr.third.org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import com.fr.third.org.apache.http.message.BasicNameValuePair;
import com.fr.third.org.apache.http.protocol.HttpContext;
import com.fr.third.org.apache.http.ssl.SSLContexts;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static com.fanruan.api.net.http.rs.HttpRequestType.POST;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-29
* <p>
* http请求工具类封装了用于http请求的各种方法
* </p>
*/
public class HttpKit {
private static final int RETRY_TIMES = 5;
private static CloseableHttpClient httpClient = null;
private final static Object SYNC_LOCK = new Object();
/**
* 根据请求地址创建HttpClient对象
*
* @param url 请求地址
* @return HttpClient对象
*/
public static CloseableHttpClient getHttpClient(String url) {
String hostname = url.split("/")[2];
int port = 80;
if (hostname.contains(":")) {
String[] arr = hostname.split(":");
hostname = arr[0];
port = Integer.parseInt(arr[1]);
}
if (httpClient == null) {
synchronized (SYNC_LOCK) {
if (httpClient == null) {
httpClient = createHttpClient(hostname, port, SSLContexts.createDefault());
}
}
}
return httpClient;
}
public static CloseableHttpClient createHttpClient(String hostname, int port, SSLContext sslContext) {
return createHttpClient(200, 40, 100, hostname, port, sslContext);
}
private static CloseableHttpClient createHttpClient(int maxTotal,
int maxPerRoute,
int maxRoute,
String hostname,
int port,
SSLContext sslContext) {
ConnectionSocketFactory socketFactory = PlainConnectionSocketFactory.getSocketFactory();
LayeredConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext);
Registry<ConnectionSocketFactory> registry = RegistryBuilder
.<ConnectionSocketFactory>create()
.register("http", socketFactory)
.register("https", sslConnectionSocketFactory)
.build();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
// 将最大连接数增加
cm.setMaxTotal(maxTotal);
// 将每个路由基础的连接增加
cm.setDefaultMaxPerRoute(maxPerRoute);
HttpHost httpHost = new HttpHost(hostname, port);
// 将目标主机的最大连接数增加
cm.setMaxPerRoute(new HttpRoute(httpHost), maxRoute);
// 请求重试处理
HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() {
@Override
public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
if (executionCount >= RETRY_TIMES) {// 如果已经重试了5次,就放弃
return false;
}
if (exception instanceof NoHttpResponseException) {// 如果服务器丢掉了连接,那么就重试
return true;
}
if (exception instanceof SSLHandshakeException) {// 不要重试SSL握手异常
return false;
}
if (exception instanceof InterruptedIOException) {// 超时
return false;
}
if (exception instanceof UnknownHostException) {// 目标服务器不可达
return false;
}
if (exception instanceof SSLException) {// SSL握手异常
return false;
}
HttpClientContext clientContext = HttpClientContext.adapt(context);
com.fr.third.org.apache.http.HttpRequest request = clientContext.getRequest();
// 如果请求是幂等的,就再次尝试
return !(request instanceof HttpEntityEnclosingRequest);
}
};
return HttpClients.custom()
.setConnectionManager(cm)
.setRetryHandler(httpRequestRetryHandler)
.build();
}
/**
* 设置 httpEntity
*
* @param requestBase 请求体
* @param httpRequest 请求
*/
private static void setHttpEntity(@NotNull HttpEntityEnclosingRequestBase requestBase, @NotNull HttpRequest httpRequest) {
HttpEntity httpEntity = httpRequest.getHttpEntity();
if (httpEntity != null) {
// 如果存在 httpEntity 直接设置
requestBase.setEntity(httpEntity);
return;
}
Map<String, String> params = httpRequest.getParams();
if (params == null || params.isEmpty()) {
return;
}
List<NameValuePair> pairs = new ArrayList<NameValuePair>();
for (Map.Entry<String, String> entry : params.entrySet()) {
pairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
try {
requestBase.setEntity(new UrlEncodedFormEntity(pairs, httpRequest.getEncoding()));
} catch (UnsupportedEncodingException e) {
LogKit.error(e.getMessage(), e);
}
}
private static <V> Map<String, String> transformMap(Map<String, V> oldMap) {
if (oldMap == null) {
return null;
}
return Maps.transformEntries(oldMap, new Maps.EntryTransformer<String, V, String>() {
@Override
public String transformEntry(@Nullable String key, @Nullable V value) {
return value == null ? null : value.toString();
}
});
}
/**
* 发起POST请求并获取返回的文本
*
* @param url 响应请求的的服务器地址
* @param params POST请求的参数
* @return 服务器返回的文本内容
*/
public static <V> String post(String url, Map<String, V> params) throws IOException {
return executeAndParse(HttpRequest
.custom()
.url(url)
.post(transformMap(params))
.build());
}
/**
* 发起POST请求并获取返回的文本
*
* @param url 响应请求的的服务器地址
* @param params POST请求的参数
* @param responseType 返回类型
* @return 服务器返回的文本内容
* @see com.fanruan.api.net.http.HttpKit#execute(HttpRequest)
*/
@Deprecated
public static <T, V> T post(String url, Map<String, V> params, HttpResponseType<T> responseType) throws IOException {
CloseableHttpResponse response = execute(HttpRequest
.custom()
.url(url)
.post(transformMap(params))
.build());
return responseType.result(response, null);
}
/**
* 发起POST请求并获取返回的文本
*
* @param url 响应请求的的服务器地址
* @param params POST请求的参数
* @param headers 请求头
* @return 服务器返回的文本内容
* @see com.fanruan.api.net.http.HttpKit#executeAndParse(HttpRequest)
*/
@Deprecated
public static <V> String post(String url, Map<String, V> params, Map<String, String> headers) throws IOException {
return executeAndParse(HttpRequest
.custom()
.url(url)
.post(transformMap(params))
.headers(headers)
.build());
}
/**
* 发起POST请求并获取返回的文本
*
* @param url 响应请求的的服务器地址
* @param params POST请求的参数
* @param headers 请求头
* @param responseType 返回类型
* @return 服务器返回的文本内容
* @see com.fanruan.api.net.http.HttpKit#execute(HttpRequest)
*/
@Deprecated
public static <T, V> T post(String url, Map<String, V> params, Map<String, String> headers, HttpResponseType<T> responseType) throws IOException {
CloseableHttpResponse response = execute(HttpRequest
.custom()
.url(url)
.post(transformMap(params))
.headers(headers)
.build());
return responseType.result(response, null);
}
/**
* 发起POST请求并获取返回的文本
*
* @param url 响应请求的的服务器地址
* @param params POST请求的参数
* @param responseEncoding 响应的文本的编码
* @return 服务器返回的文本内容
* @see com.fanruan.api.net.http.HttpKit#executeAndParse(HttpRequest, BaseHttpResponseHandle)
*/
@Deprecated
public static <V> String post(String url, Map<String, V> params, String responseEncoding) throws IOException {
return executeAndParse(HttpRequest
.custom()
.url(url)
.post(transformMap(params))
.build(),
new TextResponseHandle(responseEncoding));
}
/**
* 发起POST请求并获取返回的文本
*
* @param url 响应请求的的服务器地址
* @param params POST请求的参数
* @param responseEncoding 响应的文本的编码
* @param headers 请求头
* @return 服务器返回的文本内容
* @see com.fanruan.api.net.http.HttpKit#executeAndParse(HttpRequest, BaseHttpResponseHandle)
*/
@Deprecated
public static <V> String post(String url, Map<String, V> params, String responseEncoding, Map<String, String> headers) throws IOException {
return executeAndParse(HttpRequest
.custom()
.url(url)
.post(transformMap(params))
.headers(headers)
.build(),
new TextResponseHandle(responseEncoding));
}
/**
* 发起POST请求并获取返回的文本
*
* @param url 响应请求的的服务器地址
* @param params POST请求的参数
* @param responseEncoding 响应的文本的编码
* @param paramsEncoding 参数编码
* @param headers 请求头
* @return 服务器返回的文本内容
* @see com.fanruan.api.net.http.HttpKit#executeAndParse(HttpRequest, BaseHttpResponseHandle)
*/
public static <V> String post(String url, Map<String, V> params, String responseEncoding, String paramsEncoding, Map<String, String> headers) throws IOException {
return executeAndParse(HttpRequest
.custom()
.url(url)
.post(transformMap(params))
.encoding(paramsEncoding)
.headers(headers)
.build(),
new TextResponseHandle(responseEncoding));
}
/**
* 发起POST请求并获取返回的文本
*
* @param url 响应请求的的服务器地址
* @param params POST请求的参数
* @param responseEncoding 响应的文本的编码
* @param paramsEncoding 参数编码
* @param headers 请求头
* @param responseType 返回值类型
* @return 服务器返回的文本内容
* @see com.fanruan.api.net.http.HttpKit#execute(HttpRequest)
*/
public static <T, V> T post(String url, Map<String, V> params, String responseEncoding, String paramsEncoding, Map<String, String> headers, HttpResponseType<T> responseType) throws IOException {
CloseableHttpResponse response = execute(HttpRequest
.custom()
.url(url)
.post(transformMap(params))
.encoding(paramsEncoding)
.headers(headers)
.build());
return responseType.result(response, responseEncoding);
}
/**
* 发起GET请求并获取返回的文本
*
* @param url 响应请求的的服务器地址
* @return 服务器返回的文本内容
*/
public static String get(String url) throws IOException {
return executeAndParse(HttpRequest.custom().url(url).build());
}
/**
* 发起GET请求并获取返回的文本
*
* @param url 响应请求的的服务器地址
* @param params 参数
* @return 服务器返回的文本内容
*/
public static String get(String url, Map<String, String> params) throws IOException {
return executeAndParse(HttpRequest.custom().url(url).params(params).build());
}
/**
* 发起GET请求并获取返回的文本
*
* @param url 响应请求的的服务器地址
* @param params 参数
* @param headers 请求头
* @return 服务器返回的文本内容
* @see com.fanruan.api.net.http.HttpKit#executeAndParse(HttpRequest, BaseHttpResponseHandle)
*/
public static String get(String url, Map<String, String> params, Map<String, String> headers) throws IOException {
return executeAndParse(HttpRequest.custom().url(url).params(params).headers(headers).build());
}
/**
* 发起GET请求并获取返回的文本
*
* @param url 响应请求的的服务器地址
* @param params 参数
* @param responseEncoding 返回的文本的编码
* @return 服务器返回的文本内容
* @see com.fanruan.api.net.http.HttpKit#executeAndParse(HttpRequest, BaseHttpResponseHandle)
*/
public static String get(String url, Map<String, String> params, String responseEncoding) throws IOException {
return executeAndParse(HttpRequest
.custom()
.url(url)
.params(params)
.build(),
new TextResponseHandle(responseEncoding));
}
/**
* 发起GET请求并获取返回的文本
*
* @param url 响应请求的的服务器地址
* @param params 参数
* @param responseEncoding 返回的文本的编码
* @return 服务器返回的文本内容
* @see com.fanruan.api.net.http.HttpKit#executeAndParse(HttpRequest, BaseHttpResponseHandle)
*/
public static String get(String url, Map<String, String> params, String responseEncoding, Map<String, String> headers) throws IOException {
return executeAndParse(HttpRequest
.custom()
.url(url)
.params(params)
.headers(headers)
.build(),
new TextResponseHandle(responseEncoding));
}
/**
* 从指定的地址下载文件
* @param url 文件下载地址
* @return 文件的字节流
* @throws IOException 下载过程中出现错误则抛出此异常
*/
public static ByteArrayInputStream download(String url) throws IOException {
return executeAndParse(HttpRequest.custom().url(url).build(), StreamResponseHandle.DEFAULT);
}
/**
* 从指定的地址下载文件
* @param url 文件下载地址
* @param params 参数对
* @param responseEncoding 响应的文件编码
* @param headers 请求头
* @return 文件的字节流
* @throws IOException 下载过程中出现错误则抛出此异常
*/
public static ByteArrayInputStream download(String url, Map<String, String> params, String responseEncoding, Map<String, String> headers) throws IOException {
return executeAndParse(HttpRequest
.custom()
.url(url)
.params(params)
.headers(headers)
.build(),
new StreamResponseHandle(responseEncoding));
}
/**
* 上传文件到指定的服务器
*
* @param url 接收文件的服务器地址
* @param file 要上传的文件默认的文件编码为utf-8
* @throws IOException 上传中出现错误则抛出此异常
*/
public static void upload(String url, File file) throws IOException {
upload(url, file, Charset.forName("utf-8"));
}
/**
* 上传文件到指定的服务器
*
* @param url 接收文件的服务器地址
* @param file 要上传的文件
* @param charset 文件的编码
* @throws IOException 上传中出现错误则抛出此异常
*/
public static void upload(String url, File file, Charset charset) throws IOException {
upload(url, new FileEntity(file), charset);
}
/**
* 上传文件到指定的服务器
*
* @param url 接收文件的服务器地址
* @param builder 附件构造器
* @param charset 文件的编码
* @throws IOException 上传中出现错误则抛出此异常
*/
public static void upload(String url, MultipartEntityBuilder builder, Charset charset) throws IOException {
upload(url, builder, charset, Collections.<String, String>emptyMap(), POST);
}
/**
* 上传文件到指定的服务器
*
* @param url 接收文件的服务器地址
* @param fileEntity 文件实体
* @param charset 文件的编码
* @throws IOException 上传中出现错误则抛出此异常
*/
public static void upload(String url, FileEntity fileEntity, Charset charset) throws IOException {
upload(url, fileEntity, charset, Collections.<String, String>emptyMap(), POST);
}
/**
* 上传多文件到指定的服务器
*
* @param url 接收文件的服务器地址
* @param builder 附件构造器
* @param charset 文件的编码
* @param headers 请求头
* @param httpRequestType 请求类型
* @throws IOException 上传中出现错误则抛出此异常
*/
public static void upload(String url, MultipartEntityBuilder builder, Charset charset, Map<String, String> headers, HttpRequestType httpRequestType) throws IOException {
// richie:采用浏览器模式,防止出现乱码
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
HttpEntity reqEntity = builder.setCharset(charset).build();
upload(url, reqEntity, charset, headers, httpRequestType);
}
/**
* 上传文件到指定的服务器
*
* @param url 接收文件的服务器地址
* @param reqEntity 请求实体
* @param charset 文件的编码
* @param headers 请求头
* @param httpRequestType 请求类型
* @throws IOException 上传中出现错误则抛出此异常
*/
public static void upload(String url, HttpEntity reqEntity, Charset charset, Map<String, String> headers, HttpRequestType httpRequestType) throws IOException {
executeAndParse(HttpRequest
.custom()
.url(url)
.headers(headers)
.method(httpRequestType)
.httpEntity(reqEntity)
.encoding(charset.toString())
.build(),
UploadResponseHandle.DEFAULT);
}
/**
* 请求资源或服务使用默认文本http解析器UTF-8编码
*
* @param httpRequest httpRequest
* @return 返回处理结果
*/
public static String executeAndParse(HttpRequest httpRequest) throws IOException {
return executeAndParse(httpRequest, TextResponseHandle.DEFAULT);
}
/**
* 请求资源或服务自请求参数并指定 http 响应处理器
*
* <pre>
* String res = HttpToolbox.executeAndParse(HttpRequest
* .custom()
* .url("")
* .build(),
* TextResponseHandle.DEFAULT);
* </pre>
*
* @param httpRequest httpRequest
* @param handle http 解析器
* @return 返回处理结果
*/
public static <T> T executeAndParse(HttpRequest httpRequest, BaseHttpResponseHandle<T> handle) throws IOException {
return handle.parse(execute(httpRequest));
}
/**
* 请求资源或服务传入请求参数
*
* @param httpRequest httpRequest
* @return 返回处理结果
*/
public static CloseableHttpResponse execute(HttpRequest httpRequest) throws IOException {
return execute(getHttpClient(httpRequest.getUrl()), httpRequest);
}
/**
* 请求资源或服务自定义client对象传入请求参数
*
* @param httpClient http客户端
* @param httpRequest httpRequest
* @return 返回处理结果
*/
public static CloseableHttpResponse execute(CloseableHttpClient httpClient, HttpRequest httpRequest) throws IOException {
String url = httpRequest.getUrl();
// 创建请求对象
HttpRequestBase httpRequestBase = httpRequest.getMethod().createHttpRequest(url);
// 设置header信息
httpRequestBase.setHeader("User-Agent", "Mozilla/5.0");
Map<String, String> headers = httpRequest.getHeaders();
if (headers != null && !headers.isEmpty()) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
httpRequestBase.setHeader(entry.getKey(), entry.getValue());
}
}
// 配置请求的设置
RequestConfig requestConfig = httpRequest.getConfig();
if (requestConfig != null) {
httpRequestBase.setConfig(requestConfig);
}
// 判断是否支持设置entity(仅HttpPost、HttpPut、HttpPatch支持)
if (HttpEntityEnclosingRequestBase.class.isAssignableFrom(httpRequestBase.getClass())) {
setHttpEntity((HttpEntityEnclosingRequestBase) httpRequestBase, httpRequest);
} else {
Map<String, String> params = httpRequest.getParams();
if (params != null && !params.isEmpty()) {
// 注意get等不支持设置entity需要更新拼接之后的URL,但是url变量没有更新
httpRequestBase.setURI(URI.create(buildUrl(url, params, httpRequest.getEncoding())));
}
}
return httpClient.execute(httpRequestBase);
}
/**
* 构建 Url
*
* @param url 请求地址
* @param params 参数
* @return 拼接之后的地址
*/
public static String buildUrl(String url, Map<String, String> params) {
try {
return buildUrl(url, params, EncodeConstants.ENCODING_UTF_8);
} catch (UnsupportedEncodingException ignore) {
}
return url;
}
/**
* 构建 Url
*
* @param url 请求地址
* @param params 参数
* @return 拼接之后的地址
* @throws UnsupportedEncodingException 不支持的编码
*/
private static String buildUrl(String url, Map<String, String> params, String paramsEncoding) throws UnsupportedEncodingException {
if (params == null || params.isEmpty()) {
return url;
}
URIBuilder builder;
try {
builder = new URIBuilder(url);
for (Map.Entry<String, String> entry : params.entrySet()) {
String key = URLEncoder.encode(entry.getKey(), paramsEncoding);
String value = URLEncoder.encode(entry.getValue(), paramsEncoding);
builder.setParameter(key, value);
}
return builder.build().toString();
} catch (URISyntaxException e) {
LogKit.debug("Error to build url, please check the arguments.");
}
return url;
}
}

54
src/main/java/com/fanruan/api/net/http/rs/BaseHttpResponseHandle.java

@ -0,0 +1,54 @@
package com.fanruan.api.net.http.rs;
import com.fr.stable.EncodeConstants;
import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse;
import java.io.IOException;
/**
* http 结果解析器
*
* @author vito
* @date 2019-07-14
*/
public abstract class BaseHttpResponseHandle<T> {
/**
* 解析编码默认为 UTF_8
*/
private String encoding = EncodeConstants.ENCODING_UTF_8;
public BaseHttpResponseHandle() {
}
public BaseHttpResponseHandle(String encoding) {
this.encoding = encoding;
}
/**
* 获取解析编码
*
* @return 解析编码
*/
public String getEncoding() {
return encoding;
}
/**
* 设置解析编码
*
* @param encoding 解析编码
*/
public void setEncoding(String encoding) {
this.encoding = encoding;
}
/**
* 解析响应结果
*
* @param response 响应
* @return 解析结果
* @throws IOException io异常
*/
public abstract T parse(CloseableHttpResponse response) throws IOException;
}

215
src/main/java/com/fanruan/api/net/http/rs/HttpRequest.java

@ -0,0 +1,215 @@
package com.fanruan.api.net.http.rs;
import com.fanruan.api.macro.EncodeConstants;
import com.fr.third.org.apache.http.HttpEntity;
import com.fr.third.org.apache.http.client.config.RequestConfig;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.Map;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-29
*/
public class HttpRequest {
private static final int TIME_OUT = 10 * 1000;
private static final RequestConfig DEFAULT = RequestConfig
.custom()
.setConnectionRequestTimeout(TIME_OUT)
.setConnectTimeout(TIME_OUT)
.setSocketTimeout(TIME_OUT)
.build();
/**
* 请求地址
*/
private String url;
/**
* 请求头
*/
private Map<String, String> headers;
/**
* 请求参数
*/
private Map<String, String> params;
/**
* 请求参数
*
* @see RequestConfig
*/
@Nullable
private RequestConfig config;
/**
* 请求参数
*
* @see HttpEntity
*/
@Nullable
private HttpEntity httpEntity;
/**
* 请求方法
*/
private HttpRequestType method;
/**
* 参数字符集
*/
private String encoding;
private HttpRequest(Builder builder) {
this.url = builder.url;
this.headers = builder.headers;
this.params = builder.params;
this.config = builder.config;
this.encoding = builder.encoding;
this.httpEntity = builder.httpEntity;
this.method = builder.method;
}
public String getUrl() {
return url;
}
public Map<String, String> getHeaders() {
return headers;
}
public Map<String, String> getParams() {
return params;
}
public RequestConfig getConfig() {
return config;
}
public String getEncoding() {
return encoding;
}
public HttpEntity getHttpEntity() {
return httpEntity;
}
public HttpRequestType getMethod() {
return method;
}
public static Builder custom() {
return new Builder();
}
public static final class Builder {
private String url;
private Map<String, String> headers = Collections.emptyMap();
private Map<String, String> params = Collections.emptyMap();
@Nullable
private RequestConfig config = DEFAULT;
@Nullable
private HttpEntity httpEntity;
private String encoding = EncodeConstants.ENCODING_UTF_8;
private HttpRequestType method = HttpRequestType.GET;
private Builder() {
}
public HttpRequest build() {
if (this.url == null) {
throw new IllegalStateException("url == null");
}
return new HttpRequest(this);
}
public Builder url(@NotNull String url) {
if (url == null) {
throw new NullPointerException("url == null");
}
this.url = url;
return this;
}
public Builder headers(Map<String, String> headers) {
if (headers != null) {
this.headers = headers;
}
return this;
}
public Builder params(Map<String, String> params) {
if (params != null) {
this.params = params;
}
return this;
}
public Builder config(RequestConfig config) {
this.config = config;
return this;
}
public Builder get() {
this.method = HttpRequestType.GET;
return this;
}
public Builder post(HttpEntity httpEntity) {
this.method = HttpRequestType.POST;
this.httpEntity(httpEntity);
return this;
}
public Builder post(Map<String, String> params) {
this.method = HttpRequestType.POST;
this.params(params);
return this;
}
public Builder put(HttpEntity httpEntity) {
this.method = HttpRequestType.PUT;
this.httpEntity(httpEntity);
return this;
}
public Builder put(Map<String, String> params) {
this.method = HttpRequestType.PUT;
this.params(params);
return this;
}
public Builder delete() {
this.method = HttpRequestType.DELETE;
return this;
}
public Builder encoding(String encoding) {
if (encoding == null) {
throw new NullPointerException("httpEntity == null");
}
this.encoding = encoding;
return this;
}
public Builder httpEntity(HttpEntity httpEntity) {
this.httpEntity = httpEntity;
return this;
}
public Builder method(@NotNull HttpRequestType method) {
if (method == null) {
throw new NullPointerException("method == null");
}
this.method = method;
return this;
}
}
}

114
src/main/java/com/fanruan/api/net/http/rs/HttpRequestType.java

@ -0,0 +1,114 @@
package com.fanruan.api.net.http.rs;
import com.fr.third.org.apache.http.client.methods.HttpDelete;
import com.fr.third.org.apache.http.client.methods.HttpGet;
import com.fr.third.org.apache.http.client.methods.HttpHead;
import com.fr.third.org.apache.http.client.methods.HttpOptions;
import com.fr.third.org.apache.http.client.methods.HttpPatch;
import com.fr.third.org.apache.http.client.methods.HttpPost;
import com.fr.third.org.apache.http.client.methods.HttpPut;
import com.fr.third.org.apache.http.client.methods.HttpRequestBase;
import com.fr.third.org.apache.http.client.methods.HttpTrace;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-29
*/
public enum HttpRequestType {
/**
* 求获取Request-URI所标识的资源
*/
GET("GET") {
@Override
public HttpRequestBase createHttpRequest(String url) {
return new HttpGet(url);
}
},
/**
* 向指定资源提交数据进行处理请求例如提交表单或者上传文件数据被包含在请求体中
* POST请求可能会导致新的资源的建立和/或已有资源的修改
*/
POST("POST") {
@Override
public HttpRequestBase createHttpRequest(String url) {
return new HttpPost(url);
}
},
/**
* 向服务器索要与GET请求相一致的响应只不过响应体将不会被返回
* 这一方法可以在不必传输整个响应内容的情况下就可以获取包含在响应消息头中的元信息
* 只获取响应信息报头
*/
HEAD("HEAD") {
@Override
public HttpRequestBase createHttpRequest(String url) {
return new HttpHead(url);
}
},
/**
* 向指定资源位置上传其最新内容全部更新操作幂等
*/
PUT("PUT") {
@Override
public HttpRequestBase createHttpRequest(String url) {
return new HttpPut(url);
}
},
/**
* 请求服务器删除Request-URI所标识的资源
*/
DELETE("DELETE") {
@Override
public HttpRequestBase createHttpRequest(String url) {
return new HttpDelete(url);
}
},
/**
* 请求服务器回送收到的请求信息主要用于测试或诊断
*/
TRACE("TRACE") {
@Override
public HttpRequestBase createHttpRequest(String url) {
return new HttpTrace(url);
}
},
/**
* 向指定资源位置上传其最新内容部分更新非幂等
*/
PATCH("PATCH") {
@Override
public HttpRequestBase createHttpRequest(String url) {
return new HttpPatch(url);
}
},
/**
* 返回服务器针对特定资源所支持的HTTP请求方法
* 也可以利用向Web服务器发送'*'的请求来测试服务器的功能性
*/
OPTIONS("OPTIONS") {
@Override
public HttpRequestBase createHttpRequest(String url) {
return new HttpOptions(url);
}
};
public abstract HttpRequestBase createHttpRequest(String url);
private String name;
HttpRequestType(String name) {
this.name = name;
}
public String getName() {
return name;
}
}

103
src/main/java/com/fanruan/api/net/http/rs/HttpResponseType.java

@ -0,0 +1,103 @@
package com.fanruan.api.net.http.rs;
import com.fr.third.org.apache.http.HttpEntity;
import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse;
import com.fr.third.org.apache.http.client.methods.HttpUriRequest;
import com.fr.third.org.apache.http.client.protocol.HttpClientContext;
import com.fr.third.org.apache.http.impl.client.CloseableHttpClient;
import com.fr.third.org.apache.http.util.EntityUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-29
*/
public interface HttpResponseType<T> {
/**
* 处理http响应
*
* @param client 客户端
* @param url 地址
* @param request 请求
* @param charset 字符集
* @return 处理之后的响应
* @throws IOException 异常
*/
@Deprecated
T result(CloseableHttpClient client, String url, HttpUriRequest request, String charset) throws IOException;
/**
* 处理http响应
*
* @param response 响应
* @param charset 字符集
* @return 处理之后的响应
* @throws IOException 异常
*/
T result(CloseableHttpResponse response, String charset) throws IOException;
HttpResponseType<String> TEXT = new HttpResponseType<String>() {
@Override
public String result(CloseableHttpClient client, String url, HttpUriRequest request, String charset) throws IOException {
CloseableHttpResponse response = client.execute(request, HttpClientContext.create());
return result(response, charset);
}
@Override
public String result(CloseableHttpResponse response, String charset) throws IOException {
try {
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity, charset);
EntityUtils.consume(entity);
return result;
} finally {
if (response != null) {
response.close();
}
}
}
};
HttpResponseType<ByteArrayInputStream> STREAM = new HttpResponseType<ByteArrayInputStream>() {
@Override
public ByteArrayInputStream result(CloseableHttpClient client, String url, HttpUriRequest request, String charset) throws IOException {
CloseableHttpResponse response = client.execute(request, HttpClientContext.create());
return result(response, charset);
}
@Override
public ByteArrayInputStream result(CloseableHttpResponse response, String charset) throws IOException {
InputStream in = null;
try {
HttpEntity entity = response.getEntity();
if (entity != null) {
in = entity.getContent();
byte[] buff = new byte[8000];
int bytesRead;
ByteArrayOutputStream bao = new ByteArrayOutputStream();
while ((bytesRead = in.read(buff)) != -1) {
bao.write(buff, 0, bytesRead);
}
byte[] data = bao.toByteArray();
return new ByteArrayInputStream(data);
}
return null;
} finally {
if (response != null) {
response.close();
}
if (in != null) {
in.close();
}
}
}
};
}

55
src/main/java/com/fanruan/api/net/http/rs/StreamResponseHandle.java

@ -0,0 +1,55 @@
package com.fanruan.api.net.http.rs;
import com.fr.third.org.apache.http.HttpEntity;
import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* 流响应解析器
*
* @author vito
* @date 2019-07-14
*/
public class StreamResponseHandle extends BaseHttpResponseHandle<ByteArrayInputStream> {
public static final StreamResponseHandle DEFAULT = new StreamResponseHandle();
private static final int BUFFER_LENGTH = 8000;
public StreamResponseHandle() {
}
public StreamResponseHandle(String encoding) {
super(encoding);
}
@Override
public ByteArrayInputStream parse(CloseableHttpResponse response) throws IOException {
InputStream in = null;
try {
HttpEntity entity = response.getEntity();
if (entity != null) {
in = entity.getContent();
byte[] buff = new byte[BUFFER_LENGTH];
int bytesRead;
ByteArrayOutputStream bao = new ByteArrayOutputStream();
while ((bytesRead = in.read(buff)) != -1) {
bao.write(buff, 0, bytesRead);
}
byte[] data = bao.toByteArray();
return new ByteArrayInputStream(data);
}
return null;
} finally {
if (response != null) {
response.close();
}
if (in != null) {
in.close();
}
}
}
}

39
src/main/java/com/fanruan/api/net/http/rs/TextResponseHandle.java

@ -0,0 +1,39 @@
package com.fanruan.api.net.http.rs;
import com.fr.third.org.apache.http.HttpEntity;
import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse;
import com.fr.third.org.apache.http.util.EntityUtils;
import java.io.IOException;
/**
* 文本响应解析器
*
* @author vito
* @date 2019-07-14
*/
public class TextResponseHandle extends BaseHttpResponseHandle<String> {
public static final TextResponseHandle DEFAULT = new TextResponseHandle();
public TextResponseHandle() {
}
public TextResponseHandle(String encoding) {
super(encoding);
}
@Override
public String parse(CloseableHttpResponse response) throws IOException {
try {
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity, getEncoding());
EntityUtils.consume(entity);
return result;
} finally {
if (response != null) {
response.close();
}
}
}
}

48
src/main/java/com/fanruan/api/net/http/rs/UploadResponseHandle.java

@ -0,0 +1,48 @@
package com.fanruan.api.net.http.rs;
import com.fr.third.org.apache.http.HttpEntity;
import com.fr.third.org.apache.http.HttpStatus;
import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse;
import com.fr.third.org.apache.http.util.EntityUtils;
import java.io.IOException;
/**
* 上传响应解析器
*
* @author vito
* @date 2019-07-14
*/
public class UploadResponseHandle extends BaseHttpResponseHandle<Void> {
public static final UploadResponseHandle DEFAULT = new UploadResponseHandle();
public UploadResponseHandle() {
}
public UploadResponseHandle(String encoding) {
super(encoding);
}
@Override
public Void parse(CloseableHttpResponse response) throws IOException {
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
HttpEntity entity = response.getEntity();
if (entity != null) {
EntityUtils.consume(entity);
}
} else {
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity, getEncoding());
throw new IOException("Connect error, error code:" + statusCode + "; message:" + result);
}
} finally {
if (response != null) {
response.close();
}
}
return null;
}
}

14
src/main/java/com/fanruan/api/script/ScriptKit.java

@ -0,0 +1,14 @@
package com.fanruan.api.script;
import com.fr.script.ScriptFactory;
import javax.script.ScriptEngine;
public class ScriptKit {
/**
* 获取一个全新的脚本执行引擎
* @return 一个全新的脚本执行引擎
*/
public static ScriptEngine newScriptEngine() {
return ScriptFactory.newScriptEngine();
}
}

16
src/main/java/com/fanruan/api/util/ReflectKit.java

@ -1,16 +0,0 @@
package com.fanruan.api.util;
import com.fr.stable.StableUtils;
public class ReflectKit {
/**
* 判断一个类是否是另一个类的子类
* @param current 当前类
* @param target 目标类
* @return 如果当前类是目标类的子类则返回true否则返回false
*/
public static boolean classInstanceOf(Class current, Class target) {
return StableUtils.classInstanceOf(current, target);
}
}

32
src/main/java/com/fanruan/api/util/TypeKit.java

@ -0,0 +1,32 @@
package com.fanruan.api.util;
public class TypeKit {
/**
* 判读指定的类是否是另一个类的子类
*
* @param current 指定的类
* @param targetClass 另一个类
* @return 如果当前类是目标类的子类则返回true否则返回false
*/
public static boolean classInstanceOf(Class<?> current, Class<?> targetClass) {
if (current == null || targetClass == null) {
return false;
}
return targetClass.isAssignableFrom(current);
}
/**
* 判读指定的类是否是另一个类的子类
*
* @param object 指定的类
* @param clazz 另一个类
* @return 如果指定类是另一个类的子类则返回true否则返回false
*/
public static boolean objectInstanceOf(Object object, Class clazz) {
if (object == null || clazz == null) {
return false;
}
return clazz.isInstance(object);
}
}

39
src/main/java/com/fanruan/api/xml/XmlKit.java

@ -1,20 +1,49 @@
package com.fanruan.api.xml; package com.fanruan.api.xml;
import com.fr.general.xml.GeneralXMLTools;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLReadable; import com.fr.stable.xml.XMLReadable;
import com.fr.stable.xml.XMLTools; import com.fr.stable.xml.XMLTools;
import com.fr.stable.xml.XMLable;
import com.fr.stable.xml.XMLableReader; import com.fr.stable.xml.XMLableReader;
import com.fr.stable.xml.XMLPrintWriter;
import java.io.InputStream; import java.io.InputStream;
/**
* xml读写相关类
*/
public class XmlKit { public class XmlKit {
/** /**
* 从输入流中读取对象 * 从输入流中读取对象
* @param xmlReadable xml读取对象
* @param inputStream xml输入流
* *
* @param read xml读取对象
* @param in xml输入流
*/
public static void readInputStreamXML(XMLReadable read, InputStream in) throws Exception {
XMLTools.readInputStreamXML(read, in);
}
/**
* 将xml读取为具体的java对象
*
* @param reader xml读取器
* @return java对象
*/ */
public static void readInputStreamXML(XMLReadable xmlReadable, InputStream inputStream) throws Exception { public static XMLable readXMLable(XMLableReader reader) {
XMLTools.readInputStreamXML(xmlReadable, inputStream); return GeneralXMLTools.readXMLable(reader);
} }
/**
* 将java对象写为xml文件
*
* @param writer xml写入器
* @param xml 实际java对象
* @param tagName xml标签名
*/
public static void writeXMLable(XMLPrintWriter writer, XMLable xml, String tagName) {
GeneralXMLTools.writeXMLable(writer, xml, tagName);
}
} }

24
src/test/java/com/fanruan/api/cal/ContainerKitTest.java

@ -0,0 +1,24 @@
package com.fanruan.api.cal;
import com.fr.stable.ArrayProvider;
import com.fr.third.guava.collect.Lists;
import org.junit.Assert;
import org.junit.Test;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-29
*/
public class ContainerKitTest {
@Test
public void newArray() {
ArrayProvider<String> array = ContainerKit.newArray(new String[]{"abc", "xyz"});
Assert.assertEquals("xyz", array.elementAt(1));
ArrayProvider<String> array2 = ContainerKit.newArray(Lists.newArrayList("abc", "xyz"));
Assert.assertEquals("abc", array2.elementAt(0));
}
}

60
src/test/java/com/fanruan/api/cal/ParameterKitTest.java

@ -1,6 +1,7 @@
package com.fanruan.api.cal; package com.fanruan.api.cal;
import com.fanruan.api.Prepare; import com.fanruan.api.Prepare;
import com.fr.base.Parameter;
import com.fr.script.Calculator; import com.fr.script.Calculator;
import com.fr.stable.ParameterProvider; import com.fr.stable.ParameterProvider;
import com.fr.stable.UtilEvalError; import com.fr.stable.UtilEvalError;
@ -30,6 +31,33 @@ public class ParameterKitTest extends Prepare {
Assert.assertArrayEquals(new String[]{"p1", "p2", "p4", "p5"}, names); Assert.assertArrayEquals(new String[]{"p1", "p2", "p4", "p5"}, names);
} }
@Test
public void analyze4Parameters() {
String sql = "SELECT * FROM Equipment where 'Tel' = ${if(true, 1, 2)}";
ParameterProvider[] parameters = ParameterKit.analyze4Parameters(sql, false);
Assert.assertEquals(0, parameters.length);
parameters = ParameterKit.analyze4Parameters(sql, true);
Assert.assertEquals(0, parameters.length);
sql = "SELECT * FROM s订单 where 1=1 ${if(len(aa)==0,\"\",\" and 货主城市 in (\"+\"'\"+treelayer(aa,true,\"\\',\\'\")+\"'\"+\")\")}";
parameters = ParameterKit.analyze4Parameters(sql, false);
Assert.assertEquals(1, parameters.length);
Assert.assertEquals(parameters[0].getName(), "aa");
sql = "SELECT * FROM Equipment where 'Tel' = ${if(false, 1, 2)}";
parameters = ParameterKit.analyze4Parameters(sql, false);
Assert.assertEquals(0, parameters.length);
parameters = ParameterKit.analyze4Parameters(sql, true);
Assert.assertEquals(0, parameters.length);
sql = "SELECT * FROM s订单 where 1=1 ${if(len(aa)==0,\"\",\" and 货主城市 in (\"+\"'\"+treelayer(aa,false,\"\\',\\'\")+\"'\"+\")\")}";
parameters = ParameterKit.analyze4Parameters(sql, false);
Assert.assertEquals(1, parameters.length);
Assert.assertEquals(parameters[0].getName(), "aa");
sql = "SELECT * FROM s订单 where 1=1 ${if(len(aa)==0,\"\",\" and 货主城市 in (\"+\"'\"+treelayer(aa,\"true\",\"\\',\\'\")+\"'\"+\")\")}";
parameters = ParameterKit.analyze4Parameters(sql, false);
Assert.assertEquals(1, parameters.length);
Assert.assertEquals(parameters[0].getName(), "aa");
}
@Test @Test
public void createParameterMapNameSpace() { public void createParameterMapNameSpace() {
Map<String, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
@ -47,4 +75,36 @@ public class ParameterKitTest extends Prepare {
calculator.removeNameSpace(ns); calculator.removeNameSpace(ns);
} }
} }
@Test
public void createParameterMapNameSpace2() {
ParameterProvider[] parameters = new ParameterProvider[]{
ParameterKit.newParameter("p1", 100),
ParameterKit.newParameter("p2", 200)
};
NameSpace ns = ParameterKit.createParameterMapNameSpace(parameters);
Calculator calculator = Calculator.createCalculator();
calculator.pushNameSpace(ns);
try {
Object r = calculator.eval("=$p1 + $p2");
Assert.assertEquals(300, r);
} catch (UtilEvalError utilEvalError) {
Assert.fail();
} finally {
calculator.removeNameSpace(ns);
}
}
@Test
public void newParameter() {
ParameterProvider provider = ParameterKit.newParameter();
Assert.assertTrue(provider instanceof Parameter);
}
@Test
public void newParameter1() {
ParameterProvider provider = ParameterKit.newParameter("p1", "124");
Assert.assertEquals("p1", provider.getName());
Assert.assertEquals("124", provider.getValue());
}
} }

153
src/test/java/com/fanruan/api/net/http/HttpKitTest.java

@ -0,0 +1,153 @@
package com.fanruan.api.net.http;
import com.fanruan.api.Prepare;
import com.fanruan.api.net.http.rs.HttpRequest;
import com.fanruan.api.net.http.rs.HttpResponseType;
import com.fanruan.api.net.http.rs.StreamResponseHandle;
import com.fanruan.api.util.IOKit;
import com.fr.json.JSONObject;
import okhttp3.HttpUrl;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import org.junit.AfterClass;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketTimeoutException;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-08-29
*/
public class HttpKitTest extends Prepare {
private static MockWebServer server = new MockWebServer();
@AfterClass
public static void tearDown() throws Exception {
server.shutdown();
}
@Test
public void testGet() {
String text = null;
try {
text = HttpKit.get("http://www.baidu.com");
} catch (IOException e) {
e.printStackTrace();
}
assertNotNull(text);
}
@Test
public void testPost() {
Map<String, String> map = new HashMap<String, String>();
map.put("key", "bbs");
try {
String resText = HttpKit.post("https://cloud.fanruan.com/site", map);
assertEquals("http://bbs.fanruan.com/", new JSONObject(resText).get("value"));
} catch (SocketTimeoutException ignore) {
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
@Test
public void testStream() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("key", "bbs");
try {
InputStream in = HttpKit.post("https://cloud.fanruan.com/site", map, HttpResponseType.STREAM);
String text = IOKit.inputStream2String(in, StandardCharsets.UTF_8);
assertEquals("{\"value\":\"http://bbs.fanruan.com/\"}", text);
} catch (SocketTimeoutException ignore) {
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
@Test
public void testStreamMock() {
server.enqueue(new MockResponse().setBody("{\"value\":\"http://bbs.fanruan.com/\"}"));
String url = server.url("/site").toString();
Map<String, String> map = new HashMap<String, String>();
map.put("key", "bbs");
try {
InputStream in = HttpKit.executeAndParse(HttpRequest
.custom()
.url(url)
.post(map)
.build(),
new StreamResponseHandle());
String text = IOKit.inputStream2String(in, StandardCharsets.UTF_8);
RecordedRequest takeRequest = server.takeRequest();
assertEquals("{\"value\":\"http://bbs.fanruan.com/\"}", text);
assertEquals("POST", takeRequest.getMethod());
assertEquals("key=bbs", takeRequest.getBody().readUtf8());
} catch (SocketTimeoutException ignore) {
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
@Test
public void testMethod() throws Exception {
server.enqueue(new MockResponse().setBody("get"));
server.enqueue(new MockResponse().setBody("post"));
server.enqueue(new MockResponse().setBody("put"));
server.enqueue(new MockResponse().setBody("delete"));
String url = server.url("/v1/chat/").toString();
HttpKit.get(url);
assertEquals(server.takeRequest().getMethod(), "GET");
HttpKit.post(url, Collections.<String, String>emptyMap());
assertEquals(server.takeRequest().getMethod(), "POST");
HttpKit.executeAndParse(HttpRequest.custom().url(url).put(Collections.<String, String>emptyMap()).build());
assertEquals(server.takeRequest().getMethod(), "PUT");
HttpKit.executeAndParse(HttpRequest.custom().url(url).delete().build());
assertEquals(server.takeRequest().getMethod(), "DELETE");
}
@Test
public void testHeader() throws Exception {
server.enqueue(new MockResponse().setBody("hello, world!"));
HttpUrl baseUrl = server.url("/v1/chat/");
HashMap<String, String> headers = new HashMap<String, String>(1);
headers.put("Authorization", "abc");
String s = HttpKit.executeAndParse(HttpRequest.custom().url(baseUrl.toString()).post(Collections.<String, String>emptyMap()).headers(headers).build());
assertEquals("hello, world!", s);
// 测试请求头
RecordedRequest request = server.takeRequest();
assertEquals(request.getHeader("Authorization"), "abc");
assertEquals("POST /v1/chat/ HTTP/1.1", request.getRequestLine());
}
@Test
public void testParams() throws Exception {
server.enqueue(new MockResponse().setBody("hello, world!"));
HttpUrl baseUrl = server.url("/v1/chat/");
HashMap<String, String> params = new HashMap<String, String>(1);
params.put("key", "value");
String s = HttpKit.executeAndParse(HttpRequest.custom().url(baseUrl.toString()).post(params).build());
assertEquals("hello, world!", s);
// 测试参数
RecordedRequest request = server.takeRequest();
assertEquals("key=value", request.getBody().readUtf8());
assertEquals("POST /v1/chat/ HTTP/1.1", request.getRequestLine());
}
}

30
src/test/java/com/fanruan/api/util/GeneralKitTest.java

@ -1,9 +1,7 @@
package com.fanruan.api.util; package com.fanruan.api.util;
import com.fanruan.api.Prepare; import com.fanruan.api.Prepare;
import com.fr.third.guava.base.Objects;
import com.fr.general.GeneralUtils; import com.fr.general.GeneralUtils;
import com.fr.third.javax.persistence.criteria.CriteriaBuilder;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -20,26 +18,8 @@ public class GeneralKitTest extends Prepare {
} }
@Test @Test
public void equals() throws Exception{
Integer x = 5;
Integer y = 10;
Integer z =5;
Short a = 5;
Assert.assertEquals(GeneralKit.equals(x, y), false);
Assert.assertEquals(GeneralKit.equals(x, z), true);
Assert.assertEquals(GeneralKit.equals(z, a), false);
}
@Test
public void hashCodes() {
class A {
}
;
Object a = new A();
Assert.assertEquals(GeneralKit.hashCode(a), Objects.hashCode(a));
}
public void objectToString() { public void objectToString() {
Integer s = new Integer(1); Integer s = 1;
Assert.assertEquals(GeneralKit.objectToString(s),"1"); Assert.assertEquals(GeneralKit.objectToString(s),"1");
} }
@ -51,10 +31,10 @@ public class GeneralKitTest extends Prepare {
@Test @Test
public void compare() { public void compare() {
Integer s = new Integer(1); Integer s = 1;
Integer s3 = new Integer(1); Integer s3 = 1;
Integer s1 = new Integer(2); Integer s1 = 2;
Integer s2 = new Integer(0); Integer s2 = 0;
Assert.assertEquals(GeneralKit.compare(s,s1),-1); Assert.assertEquals(GeneralKit.compare(s,s1),-1);
Assert.assertEquals(GeneralKit.compare(s,s3),0); Assert.assertEquals(GeneralKit.compare(s,s3),0);
Assert.assertEquals(GeneralKit.compare(s,s2),1); Assert.assertEquals(GeneralKit.compare(s,s2),1);

14
src/test/java/com/fanruan/api/util/ReflectKitTest.java

@ -1,14 +0,0 @@
package com.fanruan.api.util;
import org.junit.Test;
import static org.junit.Assert.*;
public class ReflectKitTest {
@Test
public void classInstanceOf() {
assertEquals(ReflectKit.classInstanceOf(Integer.class,Object.class),true);
assertEquals(ReflectKit.classInstanceOf(Object.class,Integer.class),false);
}
}

19
src/test/java/com/fanruan/api/util/TypeKitTest.java

@ -0,0 +1,19 @@
package com.fanruan.api.util;
import org.junit.Assert;
import org.junit.Test;
public class TypeKitTest {
@Test
public void classInstanceOf() {
Assert.assertTrue(TypeKit.classInstanceOf(Integer.class, Object.class));
Assert.assertFalse(TypeKit.classInstanceOf(Object.class, Integer.class));
}
@Test
public void objectInstanceOf() {
Assert.assertTrue(TypeKit.objectInstanceOf(1, Integer.class));
Assert.assertFalse(TypeKit.objectInstanceOf(1.0, Integer.class));
}
}
Loading…
Cancel
Save