Browse Source

完成ES数据集插件

master 1.1
richie 5 years ago
parent
commit
4c6db7d805
  1. 6
      build.xml
  2. BIN
      lib/HdrHistogram-2.1.9.jar
  3. BIN
      lib/accessors-smart-1.2.jar
  4. BIN
      lib/aggs-matrix-stats-client-7.5.1.jar
  5. BIN
      lib/asm-5.0.4.jar
  6. BIN
      lib/commons-codec-1.11.jar
  7. BIN
      lib/commons-logging-1.1.3.jar
  8. BIN
      lib/compiler-0.9.6.jar
  9. BIN
      lib/elasticsearch-7.5.1.jar
  10. BIN
      lib/elasticsearch-cli-7.5.1.jar
  11. BIN
      lib/elasticsearch-core-7.5.1.jar
  12. BIN
      lib/elasticsearch-geo-7.5.1.jar
  13. BIN
      lib/elasticsearch-rest-client-7.5.1.jar
  14. BIN
      lib/elasticsearch-rest-high-level-client-7.5.1.jar
  15. BIN
      lib/elasticsearch-secure-sm-7.5.1.jar
  16. BIN
      lib/elasticsearch-ssl-config-7.5.1.jar
  17. BIN
      lib/elasticsearch-x-content-7.5.1.jar
  18. BIN
      lib/hppc-0.8.1.jar
  19. BIN
      lib/httpasyncclient-4.1.4.jar
  20. BIN
      lib/httpclient-4.5.10.jar
  21. BIN
      lib/httpcore-4.4.12.jar
  22. BIN
      lib/httpcore-nio-4.4.12.jar
  23. BIN
      lib/jackson-core-2.8.11.jar
  24. BIN
      lib/jackson-dataformat-cbor-2.8.11.jar
  25. BIN
      lib/jackson-dataformat-smile-2.8.11.jar
  26. BIN
      lib/jackson-dataformat-yaml-2.8.11.jar
  27. BIN
      lib/jna-4.5.1.jar
  28. BIN
      lib/joda-time-2.10.3.jar
  29. BIN
      lib/jopt-simple-5.0.2.jar
  30. BIN
      lib/json-path-2.4.0.jar
  31. BIN
      lib/json-smart-2.3.jar
  32. BIN
      lib/lang-mustache-client-7.5.1.jar
  33. BIN
      lib/log4j-api-2.11.1.jar
  34. BIN
      lib/lucene-analyzers-common-8.3.0.jar
  35. BIN
      lib/lucene-backward-codecs-8.3.0.jar
  36. BIN
      lib/lucene-core-8.3.0.jar
  37. BIN
      lib/lucene-grouping-8.3.0.jar
  38. BIN
      lib/lucene-highlighter-8.3.0.jar
  39. BIN
      lib/lucene-join-8.3.0.jar
  40. BIN
      lib/lucene-memory-8.3.0.jar
  41. BIN
      lib/lucene-misc-8.3.0.jar
  42. BIN
      lib/lucene-queries-8.3.0.jar
  43. BIN
      lib/lucene-queryparser-8.3.0.jar
  44. BIN
      lib/lucene-sandbox-8.3.0.jar
  45. BIN
      lib/lucene-spatial-8.3.0.jar
  46. BIN
      lib/lucene-spatial-extras-8.3.0.jar
  47. BIN
      lib/lucene-spatial3d-8.3.0.jar
  48. BIN
      lib/lucene-suggest-8.3.0.jar
  49. BIN
      lib/mapper-extras-client-7.5.1.jar
  50. BIN
      lib/netty-buffer-4.1.43.Final.jar
  51. BIN
      lib/netty-codec-4.1.43.Final.jar
  52. BIN
      lib/netty-codec-http-4.1.43.Final.jar
  53. BIN
      lib/netty-common-4.1.43.Final.jar
  54. BIN
      lib/netty-handler-4.1.43.Final.jar
  55. BIN
      lib/netty-resolver-4.1.43.Final.jar
  56. BIN
      lib/netty-transport-4.1.43.Final.jar
  57. BIN
      lib/parent-join-client-7.5.1.jar
  58. BIN
      lib/percolator-client-7.5.1.jar
  59. BIN
      lib/rank-eval-client-7.5.1.jar
  60. BIN
      lib/reindex-client-7.5.1.jar
  61. BIN
      lib/slf4j-api-1.7.25.jar
  62. BIN
      lib/snakeyaml-1.17.jar
  63. BIN
      lib/t-digest-3.2.jar
  64. BIN
      lib/transport-7.5.1.jar
  65. BIN
      lib/transport-netty4-client-7.5.1.jar
  66. 6
      plugin.xml
  67. 28
      pom.xml
  68. 20
      readme.md
  69. BIN
      screenshots/connection.png
  70. BIN
      screenshots/preview.png
  71. BIN
      screenshots/tabledata.png
  72. 85
      src/main/java/com/fr/plugin/db/es/fun/ConfigAttribute.java
  73. 136
      src/main/java/com/fr/plugin/db/es/fun/ElasticsearchConnection.java
  74. 104
      src/main/java/com/fr/plugin/db/es/fun/ElasticsearchDataModel.java
  75. 112
      src/main/java/com/fr/plugin/db/es/fun/ElasticsearchTableData.java
  76. 51
      src/main/java/com/fr/plugin/db/es/fun/assist/SimpleDataModel.java
  77. 14
      src/main/java/com/fr/plugin/db/es/fun/category/ResultStandardize.java
  78. 21
      src/main/java/com/fr/plugin/db/es/fun/category/ResultStandardizeSelector.java
  79. 166
      src/main/java/com/fr/plugin/db/es/fun/category/impl/JSONResultStandardize.java
  80. 18
      src/main/java/com/fr/plugin/db/es/fun/category/impl/JSResultStandardize.java
  81. 30
      src/main/java/com/fr/plugin/db/es/fun/category/script/EngineType.java
  82. 18
      src/main/java/com/fr/plugin/db/es/fun/category/script/ScriptBridge.java
  83. 36
      src/main/java/com/fr/plugin/db/es/fun/category/script/ScriptClientSelector.java
  84. 37
      src/main/java/com/fr/plugin/db/es/fun/category/script/client/NashornFiles.java
  85. 14
      src/main/java/com/fr/plugin/db/es/fun/category/script/client/ScriptClient.java
  86. 36
      src/main/java/com/fr/plugin/db/es/fun/category/script/client/V8Files.java
  87. 101
      src/main/java/com/fr/plugin/db/es/fun/category/script/client/impl/NashornClient.java
  88. 82
      src/main/java/com/fr/plugin/db/es/fun/category/script/client/impl/V8Client.java
  89. 28
      src/main/java/com/fr/plugin/db/es/fun/help/Console.java
  90. 53
      src/main/java/com/fr/plugin/db/es/fun/help/ElasticsearchClientFactory.java
  91. 24
      src/main/java/com/fr/plugin/db/es/fun/help/RegisterUtils.java
  92. 33
      src/main/java/com/fr/plugin/db/es/fun/help/RenderUtils.java
  93. 29
      src/main/java/com/fr/plugin/db/es/fun/type/ConverterType.java
  94. 141
      src/main/java/com/fr/plugin/db/es/ui/ElasticsearchConnectionChosePane.java
  95. 83
      src/main/java/com/fr/plugin/db/es/ui/ElasticsearchConnectionPane.java
  96. 149
      src/main/java/com/fr/plugin/db/es/ui/ElasticsearchQueryPane.java
  97. 173
      src/main/java/com/fr/plugin/db/es/ui/ElasticsearchTableDataPane.java
  98. BIN
      src/main/resources/com/fr/plugin/db/es/images/help.png
  99. BIN
      src/main/resources/com/fr/plugin/db/es/images/preview.png
  100. BIN
      src/main/resources/com/fr/plugin/db/es/images/refresh.png
  101. Some files were not shown because too many files have changed in this diff Show More

6
build.xml

@ -5,7 +5,7 @@
<property name="libs" value="${basedir}/lib"/>
<property name="publicLibs" value=""/>
<property name="reportLibs" value="${basedir}/lib/report"/>
<property name="reportLibs" value="${basedir}/../webroot/WEB-INF/lib"/>
<property name="destLoc" value="."/>
<property name="classes" value="classes"/>
<xmlproperty file="${basedir}/plugin.xml"/>
@ -84,8 +84,8 @@
<param name="resources_from" value="${basedir}"/>
</antcall>
<antcall target="compile_javas">
<param name="source_jdk_version" value="1.6"/>
<param name="target_jdk_version" value="1.6"/>
<param name="source_jdk_version" value="1.7"/>
<param name="target_jdk_version" value="1.7"/>
<param name="compile_jdk_version" value="${jdk.home}"/>
<param name="compile_files" value="${basedir}/src"/>
</antcall>

BIN
lib/HdrHistogram-2.1.9.jar

Binary file not shown.

BIN
lib/accessors-smart-1.2.jar

Binary file not shown.

BIN
lib/aggs-matrix-stats-client-7.5.1.jar

Binary file not shown.

BIN
lib/asm-5.0.4.jar

Binary file not shown.

BIN
lib/commons-codec-1.11.jar

Binary file not shown.

BIN
lib/commons-logging-1.1.3.jar

Binary file not shown.

BIN
lib/compiler-0.9.6.jar

Binary file not shown.

BIN
lib/elasticsearch-7.5.1.jar

Binary file not shown.

BIN
lib/elasticsearch-cli-7.5.1.jar

Binary file not shown.

BIN
lib/elasticsearch-core-7.5.1.jar

Binary file not shown.

BIN
lib/elasticsearch-geo-7.5.1.jar

Binary file not shown.

BIN
lib/elasticsearch-rest-client-7.5.1.jar

Binary file not shown.

BIN
lib/elasticsearch-rest-high-level-client-7.5.1.jar

Binary file not shown.

BIN
lib/elasticsearch-secure-sm-7.5.1.jar

Binary file not shown.

BIN
lib/elasticsearch-ssl-config-7.5.1.jar

Binary file not shown.

BIN
lib/elasticsearch-x-content-7.5.1.jar

Binary file not shown.

BIN
lib/hppc-0.8.1.jar

Binary file not shown.

BIN
lib/httpasyncclient-4.1.4.jar

Binary file not shown.

BIN
lib/httpclient-4.5.10.jar

Binary file not shown.

BIN
lib/httpcore-4.4.12.jar

Binary file not shown.

BIN
lib/httpcore-nio-4.4.12.jar

Binary file not shown.

BIN
lib/jackson-core-2.8.11.jar

Binary file not shown.

BIN
lib/jackson-dataformat-cbor-2.8.11.jar

Binary file not shown.

BIN
lib/jackson-dataformat-smile-2.8.11.jar

Binary file not shown.

BIN
lib/jackson-dataformat-yaml-2.8.11.jar

Binary file not shown.

BIN
lib/jna-4.5.1.jar

Binary file not shown.

BIN
lib/joda-time-2.10.3.jar

Binary file not shown.

BIN
lib/jopt-simple-5.0.2.jar

Binary file not shown.

BIN
lib/json-path-2.4.0.jar

Binary file not shown.

BIN
lib/json-smart-2.3.jar

Binary file not shown.

BIN
lib/lang-mustache-client-7.5.1.jar

Binary file not shown.

BIN
lib/log4j-api-2.11.1.jar

Binary file not shown.

BIN
lib/lucene-analyzers-common-8.3.0.jar

Binary file not shown.

BIN
lib/lucene-backward-codecs-8.3.0.jar

Binary file not shown.

BIN
lib/lucene-core-8.3.0.jar

Binary file not shown.

BIN
lib/lucene-grouping-8.3.0.jar

Binary file not shown.

BIN
lib/lucene-highlighter-8.3.0.jar

Binary file not shown.

BIN
lib/lucene-join-8.3.0.jar

Binary file not shown.

BIN
lib/lucene-memory-8.3.0.jar

Binary file not shown.

BIN
lib/lucene-misc-8.3.0.jar

Binary file not shown.

BIN
lib/lucene-queries-8.3.0.jar

Binary file not shown.

BIN
lib/lucene-queryparser-8.3.0.jar

Binary file not shown.

BIN
lib/lucene-sandbox-8.3.0.jar

Binary file not shown.

BIN
lib/lucene-spatial-8.3.0.jar

Binary file not shown.

BIN
lib/lucene-spatial-extras-8.3.0.jar

Binary file not shown.

BIN
lib/lucene-spatial3d-8.3.0.jar

Binary file not shown.

BIN
lib/lucene-suggest-8.3.0.jar

Binary file not shown.

BIN
lib/mapper-extras-client-7.5.1.jar

Binary file not shown.

BIN
lib/netty-buffer-4.1.43.Final.jar

Binary file not shown.

BIN
lib/netty-codec-4.1.43.Final.jar

Binary file not shown.

BIN
lib/netty-codec-http-4.1.43.Final.jar

Binary file not shown.

BIN
lib/netty-common-4.1.43.Final.jar

Binary file not shown.

BIN
lib/netty-handler-4.1.43.Final.jar

Binary file not shown.

BIN
lib/netty-resolver-4.1.43.Final.jar

Binary file not shown.

BIN
lib/netty-transport-4.1.43.Final.jar

Binary file not shown.

BIN
lib/parent-join-client-7.5.1.jar

Binary file not shown.

BIN
lib/percolator-client-7.5.1.jar

Binary file not shown.

BIN
lib/rank-eval-client-7.5.1.jar

Binary file not shown.

BIN
lib/reindex-client-7.5.1.jar

Binary file not shown.

BIN
lib/slf4j-api-1.7.25.jar

Binary file not shown.

BIN
lib/snakeyaml-1.17.jar

Binary file not shown.

BIN
lib/t-digest-3.2.jar

Binary file not shown.

BIN
lib/transport-7.5.1.jar

Binary file not shown.

BIN
lib/transport-netty4-client-7.5.1.jar

Binary file not shown.

6
plugin.xml

@ -3,14 +3,18 @@
<id>com.fr.plugin.db.es.v10</id>
<name><![CDATA[Elasticsearch数据集]]></name>
<active>yes</active>
<version>1.0</version>
<version>1.1</version>
<env-version>10.0</env-version>
<jartime>2019-10-25</jartime>
<vendor>fanruan.richie</vendor>
<description><![CDATA[Elasticsearch数据查询。]]></description>
<change-notes><![CDATA[
[2020-01-02]完成插件大部分功能,正式发布。<br/>
[2019-12-31]初始化插件。<br/>
]]></change-notes>
<prefer-packages>
<prefer-package>net.minidev.json</prefer-package>
</prefer-packages>
<extra-core>
<LocaleFinder class="com.fr.plugin.db.es.LocaleBridge"/>
</extra-core>

28
pom.xml

@ -8,7 +8,6 @@
<artifactId>starter</artifactId>
<version>10.0</version>
</parent>
<packaging>jar</packaging>
<artifactId>com.fr.plugin.db.es.v10</artifactId>
<dependencies>
@ -19,6 +18,11 @@
<scope>system</scope>
<systemPath>${project.basedir}/lib/finekit-10.0.jar</systemPath>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
@ -45,10 +49,28 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>6</source>
<target>6</target>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.basedir}/lib
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

20
readme.md

@ -1 +1,19 @@
# elasticsearch数据集插件
# Elasticsearch数据集插件
## 新建Elasticsearch数据连接
![connection](screenshots/connection.png)
支持连接集群,以逗号分隔多个主机地址和端口即可,确保主机地址和端口数量一致。
## 新建Elasticsearch数据集
![tabledata](screenshots/tabledata.png)
左侧区域是用于测试的,输入Elasticsearch命令后,点击执行按钮,可以在左下角输出区看到输出结果;
右侧区域是用于实际查询的,每一个输入框区域都可以使用${p}的格式带入参数。
## 预览Elasticsearch数据集
![preview](screenshots/preview.png)

BIN
screenshots/connection.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

BIN
screenshots/preview.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 KiB

BIN
screenshots/tabledata.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB

85
src/main/java/com/fr/plugin/db/es/fun/ConfigAttribute.java

@ -0,0 +1,85 @@
package com.fr.plugin.db.es.fun;
import com.fanruan.api.conf.BaseUniqueKey;
import com.fanruan.api.conf.HolderKit;
import com.fanruan.api.util.AssistKit;
import com.fr.config.holder.Conf;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLable;
import com.fr.stable.xml.XMLableReader;
/**
* @author richie
* @version 10.0
* Created by richie on 2020/1/2
*/
public class ConfigAttribute extends BaseUniqueKey implements XMLable {
public static final String XML_TAG = "ConfigAttribute";
private static final long serialVersionUID = -2125057720890342129L;
private Conf<Boolean> sorted = HolderKit.simple(false);
private Conf<Boolean> prepare = HolderKit.simple(false);
public ConfigAttribute() {
}
public boolean isSorted() {
return sorted.get();
}
public void setSorted(boolean sorted) {
this.sorted.set(sorted);
}
public boolean isPrepare() {
return prepare.get();
}
public void setPrepare(boolean prepare) {
this.prepare.set(prepare);
}
@Override
public void readXML(XMLableReader reader) {
if (reader.isChildNode()) {
String tagName = reader.getTagName();
if ("Attr".equals(tagName)) {
sorted.set(reader.getAttrAsBoolean("sorted", false));
prepare.set(reader.getAttrAsBoolean("prepare", false));
}
}
}
@Override
public void writeXML(XMLPrintWriter writer) {
writer.startTAG("Attr");
writer.attr("sorted", sorted.get());
writer.attr("prepare", prepare.get());
writer.end();
}
@Override
@SuppressWarnings("unchecked")
public Object clone() throws CloneNotSupportedException {
ConfigAttribute cloned = (ConfigAttribute) super.clone();
cloned.sorted = (Conf<Boolean>) sorted.clone();
cloned.prepare = (Conf<Boolean>) prepare.clone();
return cloned;
}
@Override
public boolean equals(Object obj) {
return obj instanceof ConfigAttribute
&& AssistKit.equals(this.sorted, ((ConfigAttribute) obj).sorted)
&& AssistKit.equals(this.prepare, ((ConfigAttribute) obj).prepare);
}
@Override
public int hashCode() {
return AssistKit.hashCode(sorted.get(), prepare.get());
}
}

136
src/main/java/com/fr/plugin/db/es/fun/ElasticsearchConnection.java

@ -1,6 +1,26 @@
package com.fr.plugin.db.es.fun;
import com.fanruan.api.conf.HolderKit;
import com.fanruan.api.data.open.BaseConnection;
import com.fanruan.api.i18n.I18nKit;
import com.fanruan.api.log.LogKit;
import com.fanruan.api.util.ArrayKit;
import com.fanruan.api.util.StringKit;
import com.fanruan.api.util.TypeKit;
import com.fr.config.Identifier;
import com.fr.config.holder.Conf;
import com.fr.data.impl.Connection;
import com.fr.plugin.db.es.fun.help.ElasticsearchClientFactory;
import com.fr.stable.collections.combination.Pair;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import java.io.IOException;
import java.util.List;
/**
* @author richie
@ -9,16 +29,130 @@ import com.fanruan.api.data.open.BaseConnection;
*/
public class ElasticsearchConnection extends BaseConnection {
public static final int DEFAULT_ES_PORT = 9200;
@Identifier("host")
private Conf<String> host = HolderKit.simple(StringKit.EMPTY);
@Identifier("port")
private Conf<String> port = HolderKit.simple(String.valueOf(DEFAULT_ES_PORT));
@Identifier("username")
private Conf<String> username = HolderKit.simple(StringKit.EMPTY);
@Identifier("password")
private Conf<String> password = HolderKit.simple(StringKit.EMPTY);
public String getHost() {
return host.get();
}
public void setHost(String host) {
this.host.set(host);
}
public String getPort() {
return port.get();
}
public void setPort(String port) {
this.port.set(port);
}
public String getUsername() {
return username.get();
}
public void setUsername(String username) {
this.username.set(username);
}
public String getPassword() {
return password.get();
}
public void setPassword(String password) {
this.password.set(password);
}
@Override
public void testConnection() throws Exception {
RestHighLevelClient client = createRestHighLevelClient();
boolean r;
try {
r = client.ping(RequestOptions.DEFAULT);
if (!r) {
throw new Exception("Failed");
}
} catch (Exception e) {
throw new Exception(e);
} finally {
client.close();
}
}
public RestHighLevelClient createRestHighLevelClient() {
Pair<String[], Integer[]> setting = setting();
return ElasticsearchClientFactory.buildHighLevelClient(setting.getFirst(), setting.getSecond(), getUsername(), getPassword());
}
public RestClient createClient() {
Pair<String[], Integer[]> setting = setting();
return ElasticsearchClientFactory.buildClient(setting.getFirst(), setting.getSecond(), getUsername(), getPassword());
}
private Pair<String[], Integer[]> setting() {
String host = getHost();
String port = getPort();
String[] hosts = host.split(",");
String[] portArr = port.split(",");
Integer[] ports = new Integer[portArr.length];
for (int i = 0; i < portArr.length; i ++) {
ports[i] = Integer.parseInt(portArr[i]);
}
return new Pair<String[], Integer[]>(hosts, ports);
}
@Override
public String connectMessage(boolean b) {
public void addConnection(List<String> list, String connectionName, Class<? extends Connection>[] acceptTypes) {
for (Class<? extends com.fr.data.impl.Connection> accept : acceptTypes) {
if (TypeKit.classInstanceOf(getClass(), accept)) {
list.add(connectionName);
break;
}
}
}
@Override
public String[] summary(String... args) {
if (ArrayKit.getLength(args) < 3) {
return ArrayKit.EMPTY_STRING_ARRAY;
}
RestClient client = createClient();
Request request = new Request(args[0], args[1]);
request.setJsonEntity(args[2]);
try {
Response response = client.performRequest(request);
return new String[]{EntityUtils.toString(response.getEntity())};
} catch (Exception e) {
LogKit.error(e.getMessage(), e);
} finally {
try {
client.close();
} catch (IOException e) {
LogKit.error(e.getMessage(), e);
}
}
return null;
}
@Override
public String connectMessage(boolean status) {
if (status) {
return I18nKit.getLocText("Plugin-Elasticsearch_Connection_Successfully") + "!";
} else {
return I18nKit.getLocText("Plugin-Elasticsearch_Connection_Failed") + "!";
}
}
@Override
public String getDriver() {
return null;

104
src/main/java/com/fr/plugin/db/es/fun/ElasticsearchDataModel.java

@ -2,6 +2,18 @@ package com.fr.plugin.db.es.fun;
import com.fanruan.api.data.open.BaseDataModel;
import com.fanruan.api.err.TableDataException;
import com.fanruan.api.util.StringKit;
import com.fr.plugin.db.es.fun.assist.SimpleDataModel;
import com.fr.plugin.db.es.fun.category.ResultStandardizeSelector;
import com.fr.plugin.db.es.fun.type.ConverterType;
import com.fr.script.Calculator;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* @author richie
@ -10,36 +22,112 @@ import com.fanruan.api.err.TableDataException;
*/
public class ElasticsearchDataModel extends BaseDataModel {
public ElasticsearchDataModel() {
private transient Calculator calculator;
private transient ElasticsearchConnection connection;
private transient String endPoint;
private transient String query;
private transient String script;
private transient ConverterType converterType;
private transient RestClient client;
private transient ConfigAttribute configAttribute;
private transient int rowCount;
private String[] columnNames;
private List<List<Object>> data;
public ElasticsearchDataModel(
Calculator calculator,
ElasticsearchConnection connection,
String endPoint,
String query,
String script,
ConverterType converterType,
ConfigAttribute configAttribute,
int rowCount) {
this.calculator = calculator;
this.connection = connection;
this.endPoint = endPoint;
this.query = query;
this.script = script;
this.converterType = converterType;
this.configAttribute = configAttribute;
this.rowCount = rowCount;
}
private void initData() throws Exception {
private void fetchData() throws TableDataException {
if (data == null) {
synchronized (ElasticsearchDataModel.class) {
if (data == null) {
try {
initData();
} catch (Exception e) {
throw new TableDataException(e.getMessage(), e);
}
}
}
}
}
private void initData() throws Exception {
if (client == null) {
client = connection.createClient();
String text;
if (StringKit.isNotBlank(endPoint)) {
Request request = new Request("GET", endPoint);
request.setJsonEntity(query);
Response response = client.performRequest(request);
text = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
} else {
text = StringKit.EMPTY;
}
SimpleDataModel simple = ResultStandardizeSelector.select(converterType).result(text, script, configAttribute, rowCount);
if (simple != null) {
this.columnNames = simple.getColumnNames();
this.data = simple.getData();
}
}
}
@Override
public int getColumnCount() throws TableDataException {
return 0;
fetchData();
return columnNames == null ? 0 : columnNames.length;
}
@Override
public String getColumnName(int i) throws TableDataException {
return null;
public String getColumnName(int columnIndex) throws TableDataException {
fetchData();
return columnNames == null ? null : columnNames[columnIndex];
}
@Override
public boolean hasRow(int rowIndex) throws com.fr.general.data.TableDataException {
fetchData();
return data != null && data.size() > rowIndex;
}
@Override
public int getRowCount() throws TableDataException {
return 0;
fetchData();
return data == null ? 0 : data.size();
}
@Override
public Object getValueAt(int i, int i1) throws TableDataException {
public Object getValueAt(int rowIndex, int columnIndex) throws TableDataException {
fetchData();
if (data != null && data.size() > rowIndex) {
List<Object> rowData = data.get(rowIndex);
if (rowData != null && rowData.size() > columnIndex) {
return rowData.get(columnIndex);
}
}
return null;
}
@Override
public void release() throws Exception {
if (client != null) {
client.close();
client = null;
}
}
}

112
src/main/java/com/fr/plugin/db/es/fun/ElasticsearchTableData.java

@ -4,18 +4,25 @@ import com.fanruan.api.conf.HolderKit;
import com.fanruan.api.data.ConnectionKit;
import com.fanruan.api.data.open.BaseTableData;
import com.fanruan.api.util.AssistKit;
import com.fanruan.api.util.StringKit;
import com.fanruan.api.xml.XmlKit;
import com.fr.base.TableData;
import com.fr.config.Identifier;
import com.fr.config.holder.Conf;
import com.fr.data.impl.Connection;
import com.fr.general.data.DataModel;
import com.fr.intelli.record.Focus;
import com.fr.plugin.db.es.fun.help.RenderUtils;
import com.fr.plugin.db.es.fun.type.ConverterType;
import com.fr.record.analyzer.EnableMetrics;
import com.fr.script.Calculator;
import com.fr.stable.Nameable;
import com.fr.stable.NameReference;
import com.fr.stable.ParameterProvider;
import com.fr.stable.xml.XMLPrintWriter;
import com.fr.stable.xml.XMLableReader;
import java.util.Collection;
/**
* @author richie
* @version 10.0
@ -24,7 +31,18 @@ import com.fr.stable.xml.XMLableReader;
@EnableMetrics
public class ElasticsearchTableData extends BaseTableData {
@Identifier("database")
private Conf<Connection> database = HolderKit.obj(null, Connection.class);
@Identifier("endPoint")
private Conf<String> endPoint = HolderKit.simple(StringKit.EMPTY);
@Identifier("query")
private Conf<String> query = HolderKit.simple(StringKit.EMPTY);
@Identifier("script")
private Conf<String> script = HolderKit.simple(StringKit.EMPTY);
@Identifier("converterType")
private Conf<Integer> converterType = HolderKit.simple(ConverterType.JSON.toInt());
@Identifier("configAttribute")
private Conf<ConfigAttribute> configAttribute = HolderKit.obj(new ConfigAttribute(), ConfigAttribute.class);
public ElasticsearchTableData() {
@ -38,6 +56,46 @@ public class ElasticsearchTableData extends BaseTableData {
this.database.set(database);
}
public String getEndPoint() {
return endPoint.get();
}
public void setEndPoint(String endPoint) {
this.endPoint.set(endPoint);
}
public String getQuery() {
return query.get();
}
public void setQuery(String query) {
this.query.set(query);
}
public String getScript() {
return script.get();
}
public void setScript(String script) {
this.script.set(script);
}
public ConverterType getConverterType() {
return ConverterType.parse(converterType.get());
}
public void setConverterType(ConverterType converterType) {
this.converterType.set(converterType.toInt());
}
public ConfigAttribute getConfigAttribute() {
return configAttribute.get();
}
public void setConfigAttribute(ConfigAttribute configAttribute) {
this.configAttribute.set(configAttribute);
}
@Override
public DataModel createDataModel(Calculator calculator) {
return createDataModel(calculator, TableData.RESULT_ALL);
@ -47,15 +105,27 @@ public class ElasticsearchTableData extends BaseTableData {
@Focus(id = "com.fr.plugin.db.es.v10", text = "Plugin_Elasticsearch_Table_Data")
public DataModel createDataModel(Calculator calculator, int rowCount) {
ElasticsearchConnection connection = getConnection();
Collection parameterCollection = this.parameters.get();
ParameterProvider[] parameterProviders = (ParameterProvider[]) parameterCollection.toArray(new ParameterProvider[0]);
ParameterProvider[] ps = Calculator.processParameters(calculator, parameterProviders);
if (connection != null) {
return new ElasticsearchDataModel();
return new ElasticsearchDataModel(
calculator,
connection,
RenderUtils.calculateQuery(endPoint.get(), ps),
RenderUtils.calculateQuery(query.get(), ps),
RenderUtils.calculateQuery(script.get(), ps),
getConverterType(),
getConfigAttribute(),
rowCount
);
}
return null;
}
private ElasticsearchConnection getConnection() {
if (database.get() instanceof Nameable) {
String name = ((Nameable) database.get()).getName();
if (database.get() instanceof NameReference) {
String name = ((NameReference) database.get()).getName();
return ConnectionKit.getConnection(name, ElasticsearchConnection.class);
}
return null;
@ -72,6 +142,19 @@ public class ElasticsearchTableData extends BaseTableData {
Connection con = XmlKit.readXMLConnection(reader);
this.setDatabase(con);
}
} else if ("Query".equals(tmpName)) {
if ((tmpVal = reader.getElementValue()) != null) {
this.setQuery(tmpVal);
}
} if ("Script".equals(tmpName)) {
if ((tmpVal = reader.getElementValue()) != null) {
this.setQuery(tmpVal);
}
} else if (ConfigAttribute.XML_TAG.equals(tmpName)) {
configAttribute.set((ConfigAttribute) XmlKit.readXMLable(reader));
} else if ("Attr".equals(tmpName)) {
setEndPoint(reader.getAttrAsString("endPoint", StringKit.EMPTY));
setConverterType(ConverterType.parse(reader.getAttrAsInt("converterType", ConverterType.JSON.toInt())));
}
}
}
@ -82,23 +165,40 @@ public class ElasticsearchTableData extends BaseTableData {
if (this.database.get() != null) {
XmlKit.writeXMLConnection(writer, this.database.get());
}
if (configAttribute.get() != null) {
XmlKit.writeXMLable(writer, configAttribute.get(), ConfigAttribute.XML_TAG);
}
writer.startTAG("Query").textNode(getQuery()).end();
writer.startTAG("Script").textNode(getQuery()).end();
writer.startTAG("Attr");
writer.attr("endPoint", getEndPoint());
writer.attr("converterType", getConverterType().toInt());
writer.end();
}
@Override
public Object clone() throws CloneNotSupportedException {
ElasticsearchTableData cloned = (ElasticsearchTableData) super.clone();
cloned.database = (Conf<Connection>) database.clone();
cloned.endPoint = (Conf<String>) endPoint.clone();
cloned.converterType = (Conf<Integer>) converterType.clone();
cloned.query = (Conf<String>) query.clone();
cloned.script = (Conf<String>) script.clone();
return cloned;
}
@Override
public boolean equals(Object obj) {
return obj instanceof ElasticsearchTableData
&& AssistKit.equals(database, ((ElasticsearchTableData) obj).database);
&& AssistKit.equals(database, ((ElasticsearchTableData) obj).database)
&& AssistKit.equals(endPoint, ((ElasticsearchTableData) obj).endPoint)
&& AssistKit.equals(converterType, ((ElasticsearchTableData) obj).converterType)
&& AssistKit.equals(query, ((ElasticsearchTableData) obj).query)
&& AssistKit.equals(script, ((ElasticsearchTableData) obj).script);
}
@Override
public int hashCode() {
return AssistKit.hashCode(database.get());
return AssistKit.hashCode(database.get(), endPoint.get(), converterType.get(), query.get(), script.get());
}
}

51
src/main/java/com/fr/plugin/db/es/fun/assist/SimpleDataModel.java

@ -0,0 +1,51 @@
package com.fr.plugin.db.es.fun.assist;
import java.util.ArrayList;
import java.util.List;
/**
* @author richie
* @version 10.0
* Created by richie on 2020/1/2
*/
public class SimpleDataModel {
private List<List<Object>> data = new ArrayList<List<Object>>();
private String[] columnNames = null;
private int rowCount;
public SimpleDataModel(String[] columnNames, List<List<Object>> data){
this.columnNames = columnNames;
this.data = data;
}
public SimpleDataModel(String[] columnNames, List<List<Object>> data, int rowCount){
this.columnNames = columnNames;
this.data = data;
this.rowCount = rowCount;
}
public List<List<Object>> getData() {
return data;
}
public void setData(List<List<Object>> data) {
this.data = data;
}
public String[] getColumnNames() {
return columnNames;
}
public void setColumnNames(String[] columnNames) {
this.columnNames = columnNames;
}
public int getRowCount() {
return rowCount;
}
public void setRowCount(int rowCount) {
this.rowCount = rowCount;
}
}

14
src/main/java/com/fr/plugin/db/es/fun/category/ResultStandardize.java

@ -0,0 +1,14 @@
package com.fr.plugin.db.es.fun.category;
import com.fr.plugin.db.es.fun.ConfigAttribute;
import com.fr.plugin.db.es.fun.assist.SimpleDataModel;
/**
* @author richie
* @version 10.0
* Created by richie on 2020/1/2
*/
public interface ResultStandardize {
SimpleDataModel result(String text, String script, ConfigAttribute configAttribute, int rowCount);
}

21
src/main/java/com/fr/plugin/db/es/fun/category/ResultStandardizeSelector.java

@ -0,0 +1,21 @@
package com.fr.plugin.db.es.fun.category;
import com.fr.plugin.db.es.fun.category.impl.JSONResultStandardize;
import com.fr.plugin.db.es.fun.category.impl.JSResultStandardize;
import com.fr.plugin.db.es.fun.type.ConverterType;
/**
* @author richie
* @version 10.0
* Created by richie on 2020/1/2
*/
public class ResultStandardizeSelector {
public static ResultStandardize select(ConverterType converterType) {
if (converterType == ConverterType.JSON) {
return new JSONResultStandardize();
} else {
return new JSResultStandardize();
}
}
}

166
src/main/java/com/fr/plugin/db/es/fun/category/impl/JSONResultStandardize.java

@ -0,0 +1,166 @@
package com.fr.plugin.db.es.fun.category.impl;
import com.fr.plugin.db.es.fun.ConfigAttribute;
import com.fr.plugin.db.es.fun.assist.SimpleDataModel;
import com.fr.plugin.db.es.fun.category.ResultStandardize;
import com.jayway.jsonpath.JsonPath;
import net.minidev.json.JSONArray;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
/**
* @author richie
* @version 10.0
* Created by richie on 2020/1/2
*/
public class JSONResultStandardize implements ResultStandardize {
private List<String> columnNames = new ArrayList<>();
private List<List<Object>> data = new ArrayList<List<Object>>();
@Override
public SimpleDataModel result(String text, String script, ConfigAttribute configAttribute, int rowCount) {
Object object = JsonPath.read(text, script);
if (object instanceof LinkedHashMap) {
initJSONObject(new TreeMap<>((LinkedHashMap<String, Object>) object));
} else if (object instanceof JSONArray) {
initJSONArray((JSONArray) object, configAttribute);
} else {
initSingleData(object);
}
return new SimpleDataModel(columnNames.toArray(new String[0]), data);
}
private Map<String, Object> transferMap(Map<String, Object> data, ConfigAttribute attr) {
if (attr.isSorted()) {
return new TreeMap<>(data);
}
return data;
}
private void initJSONObject(Map<String, Object> map) {
List<Object> row = new ArrayList<Object>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
columnNames.add(entry.getKey());
row.add(entry.getValue());
}
data.add(row);
}
private void initJSONArray(JSONArray jsonArray, ConfigAttribute attr) {
if (attr.isPrepare()) {
iterateAllColumn(jsonArray, attr);
} else {
quickAttach(jsonArray, attr);
}
}
private int findColumnIndexByName(String columnName) {
for (int i = 0, len = columnNames.size(); i < len; i++) {
if (columnName.equals(columnNames.get(i))) {
return i;
}
}
return -1;
}
private void quickAttach(JSONArray jsonArray, ConfigAttribute attr) {
boolean findMap = false;
boolean colGet = false;
Set<String> extraColumns = new LinkedHashSet<String>();
for (Object obj : jsonArray) {
List<Object> row = new ArrayList<Object>();
if (obj instanceof LinkedHashMap) {
findMap = true;
Map<String, Object> map = transferMap((LinkedHashMap<String, Object>) obj, attr);
Map<String, Object> lazy = new LinkedHashMap<String, Object>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
if (!colGet) {
columnNames.add(key);
}
if (findColumnIndexByName(key) != -1) {
row.add(entry.getValue());
} else {
lazy.put(key, entry.getValue());
}
}
for (Map.Entry<String, Object> entry : lazy.entrySet()) {
row.add(entry.getValue());
extraColumns.add(entry.getKey());
}
colGet = true;
data.add(row);
} else if (obj instanceof JSONArray) {
findMap = true;
JSONArray array = (JSONArray) obj;
for (int i = 0, len = array.size(); i < len; i++) {
if (!colGet) {
columnNames.add("value" + (i + 1));
}
row.add(array.get(i));
}
colGet = true;
data.add(row);
}
}
columnNames.addAll(extraColumns);
if (!findMap) {
columnNames.add("value");
for (Object obj : jsonArray) {
List<Object> row = new ArrayList<Object>();
row.add(obj);
data.add(row);
}
}
}
private void iterateAllColumn(JSONArray jsonArray, ConfigAttribute attr) {
Set<String> columnString = transferColumnSet(attr);
for (Object obj : jsonArray) {
if (obj instanceof LinkedHashMap) {
Map<String, Object> map = transferMap((LinkedHashMap<String, Object>) obj, attr);
columnString.addAll(map.keySet());
} else {
throw new RuntimeException("Illegal format, data must be JSONObject!");
}
}
columnNames = new ArrayList<>(columnString);
for (Object obj : jsonArray) {
List<Object> row = new ArrayList<Object>();
if (obj instanceof LinkedHashMap) {
Map<String, Object> map = (LinkedHashMap<String, Object>) obj;
for (String key : columnNames) {
row.add(map.get(key));
}
}
data.add(row);
}
}
private Set<String> transferColumnSet(ConfigAttribute attr) {
if (attr.isSorted()) {
return new TreeSet<>();
}
return new HashSet<>();
}
private void initSingleData(Object obj) {
columnNames.add("value");
List<Object> row = new ArrayList<>();
row.add(obj);
data.add(row);
}
}

18
src/main/java/com/fr/plugin/db/es/fun/category/impl/JSResultStandardize.java

@ -0,0 +1,18 @@
package com.fr.plugin.db.es.fun.category.impl;
import com.fr.plugin.db.es.fun.ConfigAttribute;
import com.fr.plugin.db.es.fun.assist.SimpleDataModel;
import com.fr.plugin.db.es.fun.category.ResultStandardize;
import com.fr.plugin.db.es.fun.category.script.ScriptClientSelector;
/**
* @author richie
* @version 10.0
* Created by richie on 2020/1/2
*/
public class JSResultStandardize implements ResultStandardize {
@Override
public SimpleDataModel result(String text, String script, ConfigAttribute configAttribute, int rowCount) {
return ScriptClientSelector.auto().build(text, script, rowCount);
}
}

30
src/main/java/com/fr/plugin/db/es/fun/category/script/EngineType.java

@ -0,0 +1,30 @@
package com.fr.plugin.db.es.fun.category.script;
/**
* @author richie
* @version 10.0
* Created by richie on 2019/12/30
*/
public enum EngineType {
V8(0), JAVA(1);
private int index;
EngineType(int index) {
this.index = index;
}
public int getType() {
return index;
}
public static EngineType parse(int type) {
for (EngineType engineType : values()) {
if (engineType.index == type) {
return engineType;
}
}
return V8;
}
}

18
src/main/java/com/fr/plugin/db/es/fun/category/script/ScriptBridge.java

@ -0,0 +1,18 @@
package com.fr.plugin.db.es.fun.category.script;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author richie
* @version 10.0
* Created by richie on 2019/12/30
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ScriptBridge {
}

36
src/main/java/com/fr/plugin/db/es/fun/category/script/ScriptClientSelector.java

@ -0,0 +1,36 @@
package com.fr.plugin.db.es.fun.category.script;
import com.eclipsesource.v8.V8;
import com.fr.plugin.db.es.fun.category.script.client.ScriptClient;
import com.fr.plugin.db.es.fun.category.script.client.impl.NashornClient;
import com.fr.plugin.db.es.fun.category.script.client.impl.V8Client;
/**
* @author richie
* @version 10.0
* Created by richie on 2019/12/30
* JS客户端选择器
*/
public class ScriptClientSelector {
private final static boolean SUPPORT_J2V8 = isSupportJ2v8();
public static boolean isSupportJ2v8() {
V8 v8;
try {
v8 = V8.createV8Runtime();
} catch (IllegalStateException ex) {
return false;
}
v8.release();
return true;
}
public static ScriptClient auto() {
if (SUPPORT_J2V8) {
return new V8Client();
} else {
return new NashornClient();
}
}
}

37
src/main/java/com/fr/plugin/db/es/fun/category/script/client/NashornFiles.java

@ -0,0 +1,37 @@
package com.fr.plugin.db.es.fun.category.script.client;
import com.fanruan.api.log.LogKit;
import com.fanruan.api.macro.EncodeConstants;
import com.fanruan.api.util.IOKit;
import com.fr.plugin.db.es.fun.category.script.ScriptBridge;
import javax.script.ScriptEngine;
import java.io.InputStream;
/**
* @author richie
* @version 10.0
* Created by richie on 2019/12/30
*/
public class NashornFiles {
private ScriptEngine scriptEngine;
public NashornFiles(ScriptEngine scriptEngine) {
this.scriptEngine = scriptEngine;
}
@ScriptBridge
public void require(String filePath) {
InputStream in = IOKit.readResource(filePath);
if (in != null) {
try {
String text = IOKit.inputStream2String(in, EncodeConstants.ENCODING_UTF_8);
scriptEngine.eval(text);
} catch (Exception e) {
LogKit.error(e.getMessage(), e);
}
}
}
}

14
src/main/java/com/fr/plugin/db/es/fun/category/script/client/ScriptClient.java

@ -0,0 +1,14 @@
package com.fr.plugin.db.es.fun.category.script.client;
import com.fr.plugin.db.es.fun.assist.SimpleDataModel;
/**
* @author richie
* @version 10.0
* Created by richie on 2019/12/30
*/
public interface ScriptClient {
SimpleDataModel build(String text, String query, int limit);
}

36
src/main/java/com/fr/plugin/db/es/fun/category/script/client/V8Files.java

@ -0,0 +1,36 @@
package com.fr.plugin.db.es.fun.category.script.client;
import com.eclipsesource.v8.V8;
import com.fanruan.api.macro.EncodeConstants;
import com.fanruan.api.util.IOKit;
import com.fr.plugin.db.es.fun.category.script.ScriptBridge;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
/**
* @author richie
* @version 10.0
* Created by richie on 2019/12/30
*/
public class V8Files {
private V8 v8;
public V8Files(V8 v8) {
this.v8 = v8;
}
@ScriptBridge
public void require(String filePath) {
InputStream in = IOKit.readResource(filePath);
if (in != null) {
try {
v8.executeVoidScript(IOKit.inputStream2String(in, EncodeConstants.ENCODING_UTF_8));
} catch (UnsupportedEncodingException ignore) {
}
}
}
}

101
src/main/java/com/fr/plugin/db/es/fun/category/script/client/impl/NashornClient.java

@ -0,0 +1,101 @@
package com.fr.plugin.db.es.fun.category.script.client.impl;
import com.fr.base.TableData;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.db.es.fun.assist.SimpleDataModel;
import com.fr.plugin.db.es.fun.category.script.client.NashornFiles;
import com.fr.plugin.db.es.fun.category.script.client.ScriptClient;
import com.fr.plugin.db.es.fun.help.Console;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* @author richie
* @version 10.0
* Created by richie on 2019/12/30
*/
public class NashornClient implements ScriptClient {
private static final String PREPARE_SCRIPT =
"function unique(array) {var res = [];for (var i = 0, arrayLen = array.length; i < arrayLen; i++) {for (var j = 0, resLen = res.length; j < resLen; j++ ) {if (array[i] === res[j]) {break;}} if (j === resLen) {res.push(array[i])}} return res;}\n" +
"function merge(table, column) {return {content:table, column:column}};";
private ScriptEngine scriptEngine;
public NashornClient() {
this.scriptEngine = findScriptEngine();
}
@Override
public SimpleDataModel build(String text, String query, int limit) {
scriptEngine.put("console", new Console());
scriptEngine.put("Files", new NashornFiles(scriptEngine));
try {
scriptEngine.eval(PREPARE_SCRIPT);
Map<String, Map<String, Object>> r = (Map<String, Map<String, Object>>) scriptEngine.eval(String.format(
"(function($){var $data = $; %s})(%s);", query, text));
Map<String, Object> columns = r.get("column");
int columnCount = columns.size();
String[] columnNames = new String[columnCount];
int k = 0;
for (Map.Entry<String, Object> entry : columns.entrySet()) {
columnNames[k] = String.valueOf(entry.getValue());
k++;
}
Map<String, Object> content = r.get("content");
int returnRowCount = content.size();
int realCount = limit == TableData.RESULT_ALL ? returnRowCount : Math.min(returnRowCount, limit);
List<List<Object>> data = new ArrayList<List<Object>>();
int i = 0;
for (Map.Entry<String, Object> entry : content.entrySet()) {
if (i >= realCount) {
break;
}
List<Object> row = new ArrayList<Object>();
Object el = entry.getValue();
if (el instanceof Map) {
Map<String, Object> rowCollection = (Map<String, Object>) entry.getValue();
for (Map.Entry<String, Object> rowEntry : rowCollection.entrySet()) {
row.add(rowEntry.getValue());
}
} else if (el instanceof Object[]) {
Object[] array = (Object[]) el;
row.addAll(Arrays.asList(array));
}
data.add(row);
i++;
}
return new SimpleDataModel(columnNames, data, realCount);
} catch (ScriptException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return null;
}
private static ScriptEngine findScriptEngine() {
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine engine = scriptEngineManager.getEngineByName("nashorn");
if (engine == null) {
List<ScriptEngineFactory> factories = scriptEngineManager.getEngineFactories();
for (ScriptEngineFactory factory : factories) {
ScriptEngine current = factory.getScriptEngine();
if (current != null) {
engine = current;
}
}
}
return engine;
}
}

82
src/main/java/com/fr/plugin/db/es/fun/category/script/client/impl/V8Client.java

@ -0,0 +1,82 @@
package com.fr.plugin.db.es.fun.category.script.client.impl;
import com.eclipsesource.v8.V8;
import com.eclipsesource.v8.V8Array;
import com.eclipsesource.v8.V8Object;
import com.fr.base.TableData;
import com.fr.plugin.db.es.fun.assist.SimpleDataModel;
import com.fr.plugin.db.es.fun.category.script.client.ScriptClient;
import com.fr.plugin.db.es.fun.category.script.client.V8Files;
import com.fr.plugin.db.es.fun.help.Console;
import com.fr.plugin.db.es.fun.help.RegisterUtils;
import java.util.ArrayList;
import java.util.List;
/**
* @author richie
* @version 10.0
* Created by richie on 2019/12/30
*/
public class V8Client implements ScriptClient {
private V8 v8;
public V8Client() {
this.v8 = V8.createV8Runtime();
}
@Override
public SimpleDataModel build(String text, String query, int limit) {
V8Object v8Console = initConsole(v8);
V8Object v8Require = initRequire(v8);
v8.executeVoidScript(
"function unique(array) {return Array.from(new Set(array));};" +
"function merge(table, column) {return {content:table, column:column}};");
V8Object returnObj = v8.executeObjectScript(String.format(
"(function($){var $data = $; %s})(%s);", query, text));
V8Array v8Column = returnObj.getArray("column");
V8Array v8Table = returnObj.getArray("content");
int columnCount = v8Column.length();
String[] columnNames = new String[columnCount];
for (int i = 0; i < columnCount; i++) {
columnNames[i] = String.valueOf(v8Column.get(i));
}
int returnRowCount = v8Table.length();
int realCount = limit == TableData.RESULT_ALL ? returnRowCount : Math.min(returnRowCount, limit);
List<List<Object>> data = new ArrayList<List<Object>>();
for (int i = 0; i < realCount; i++) {
V8Array v8Row = v8Table.getArray(i);
List<Object> row = new ArrayList<Object>();
for (int j = 0, col = v8Row.length(); j < col; j++) {
row.add(v8Row.get(j));
}
v8Row.release();
data.add(row);
}
v8Require.release();
v8Console.release();
v8Table.release();
v8Column.release();
returnObj.release();
v8.release(true);
return new SimpleDataModel(columnNames, data, realCount);
}
private V8Object initConsole(V8 v8) {
V8Object v8Console = new V8Object(v8);
v8.add("console", v8Console);
Console console = new Console();
RegisterUtils.registerJavaMethods(v8Console, console);
return v8Console;
}
private V8Object initRequire(V8 v8) {
V8Object v8Files = new V8Object(v8);
v8.add("Files", v8Files);
V8Files files = new V8Files(v8);
RegisterUtils.registerJavaMethods(v8Files, files);
return v8Files;
}
}

28
src/main/java/com/fr/plugin/db/es/fun/help/Console.java

@ -0,0 +1,28 @@
package com.fr.plugin.db.es.fun.help;
import com.fanruan.api.log.LogKit;
import com.fr.plugin.db.es.fun.category.script.ScriptBridge;
import com.fr.plugin.db.es.fun.category.script.ScriptClientSelector;
/**
* @author richie
* @version 10.0
* Created by richie on 2020/1/2
*/
public class Console {
@ScriptBridge
public void log(Object message) {
LogKit.info(message == null ? null : message.toString());
}
@ScriptBridge
public void error(Object message) {
LogKit.error(message == null ? null : message.toString());
}
@ScriptBridge
public String engine() {
return ScriptClientSelector.isSupportJ2v8() ? "V8" : "Nashorn";
}
}

53
src/main/java/com/fr/plugin/db/es/fun/help/ElasticsearchClientFactory.java

@ -0,0 +1,53 @@
package com.fr.plugin.db.es.fun.help;
import com.fanruan.api.util.ArrayKit;
import com.fanruan.api.util.StringKit;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
/**
* @author richie
* @version 10.0
* Created by richie on 2019/12/31
*/
public class ElasticsearchClientFactory {
public static RestHighLevelClient buildHighLevelClient(String[] hosts, Integer[] ports, String username, String password) {
return new RestHighLevelClient(build(hosts, ports, username, password));
}
public static RestClient buildClient(String[] hosts, Integer[] ports, String username, String password) {
return build(hosts, ports, username, password).build();
}
private static RestClientBuilder build(String[] hosts, Integer[] ports, String username, String password) {
int hostCount = ArrayKit.getLength(hosts);
int portCount = ArrayKit.getLength(ports);
if (portCount != hostCount) {
throw new IllegalArgumentException("Hosts and ports must be matched!");
}
HttpHost[] httpHosts = new HttpHost[hostCount];
for (int i = 0; i < hostCount; i++) {
httpHosts[i] = new HttpHost(hosts[i], ports[i], "http");
}
RestClientBuilder builder = RestClient.builder(httpHosts);
if (StringKit.isNotEmpty(username)) {
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
builder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) {
return httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
}
});
}
return builder;
}
}

24
src/main/java/com/fr/plugin/db/es/fun/help/RegisterUtils.java

@ -0,0 +1,24 @@
package com.fr.plugin.db.es.fun.help;
import com.eclipsesource.v8.V8Object;
import com.fr.plugin.db.es.fun.category.script.ScriptBridge;
import java.lang.reflect.Method;
/**
* @author richie
* @version 10.0
* Created by richie on 2020/1/2
*/
public class RegisterUtils {
public static void registerJavaMethods(V8Object v8Object, Object target) {
Method[] methods = target.getClass().getMethods();
for (Method m : methods) {
if (m.getAnnotation(ScriptBridge.class) != null) {
v8Object.registerJavaMethod(target, m.getName(), m.getName(), m.getParameterTypes());
}
}
}
}

33
src/main/java/com/fr/plugin/db/es/fun/help/RenderUtils.java

@ -0,0 +1,33 @@
package com.fr.plugin.db.es.fun.help;
import com.fanruan.api.util.RenderKit;
import com.fr.base.Parameter;
import com.fr.base.TemplateUtils;
import com.fr.stable.ArrayUtils;
import com.fr.stable.ParameterProvider;
import java.util.HashMap;
import java.util.Map;
/**
* @author richie
* @version 10.0
* Created by richie on 2019/12/31
*/
public class RenderUtils {
public static String calculateQuery(String query, ParameterProvider[] ps) {
if (ArrayUtils.isEmpty(ps)) {
return query;
}
Map<String, Object> map = new HashMap<>();
for (ParameterProvider p : ps) {
map.put(p.getName(), p.getValue());
}
try {
return RenderKit.renderParameter4Tpl(query, map);
} catch (Exception e) {
return query;
}
}
}

29
src/main/java/com/fr/plugin/db/es/fun/type/ConverterType.java

@ -0,0 +1,29 @@
package com.fr.plugin.db.es.fun.type;
/**
* @author richie
* @version 10.0
* Created by richie on 2019/12/31
*/
public enum ConverterType {
JSON(0), JS(1);
private int i;
ConverterType(int i) {
this.i = i;
}
public int toInt() {
return i;
}
public static ConverterType parse(int i) {
for (ConverterType type : values()) {
if (i == type.i) {
return type;
}
}
return JSON;
}
}

141
src/main/java/com/fr/plugin/db/es/ui/ElasticsearchConnectionChosePane.java

@ -0,0 +1,141 @@
package com.fr.plugin.db.es.ui;
import com.fanruan.api.data.ConnectionKit;
import com.fanruan.api.design.macro.UIConstants;
import com.fanruan.api.design.ui.component.UIButton;
import com.fanruan.api.design.ui.component.UIDictionaryComboBox;
import com.fanruan.api.design.ui.component.UIPlaceholderTextField;
import com.fanruan.api.design.ui.component.UIRoundedBorder;
import com.fanruan.api.design.ui.component.code.SyntaxConstants;
import com.fanruan.api.design.ui.component.code.UISyntaxTextArea;
import com.fanruan.api.design.ui.component.code.UISyntaxTextScrollPane;
import com.fanruan.api.design.util.GUICoreKit;
import com.fanruan.api.design.work.ConnectionComboBoxPanel;
import com.fanruan.api.log.LogKit;
import com.fanruan.api.util.ArrayKit;
import com.fanruan.api.util.IOKit;
import com.fr.data.impl.Connection;
import com.fr.design.dialog.BasicPane;
import com.fr.plugin.db.es.fun.ElasticsearchConnection;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
/**
* @author richie
* @version 10.0
* Created by richie on 2020/1/2
*/
public class ElasticsearchConnectionChosePane extends BasicPane {
private ConnectionComboBoxPanel connectionComboBoxPanel;
private UIDictionaryComboBox<String> typeComboBox;
private UIPlaceholderTextField queryAllTextField;
private UISyntaxTextArea consoleTextPane;
private UISyntaxTextArea outputTextPane;
public ElasticsearchConnectionChosePane() {
setLayout(new BorderLayout(4, 4));
connectionComboBoxPanel = new ConnectionComboBoxPanel(Connection.class) {
protected void filterConnection(Connection connection, String conName, List<String> nameList) {
connection.addConnection(nameList, conName, new Class[]{ElasticsearchConnection.class});
}
};
add(connectionComboBoxPanel, BorderLayout.NORTH);
connectionComboBoxPanel.addComboBoxActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
}
});
JPanel centerPane = new JPanel(new BorderLayout());
add(centerPane, BorderLayout.CENTER);
typeComboBox = new UIDictionaryComboBox<>(new String[]{
"GET", "POST", "PUT"
}, new String[]{
"GET", "POST", "PUT"
});
typeComboBox.setSelectedItem("GET");
queryAllTextField = new UIPlaceholderTextField();
queryAllTextField.setText("/_search?pretty=true");
UIButton execButton = new UIButton(IOKit.readIcon("/com/fr/plugin/db/es/images/run.png"));
execButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
run();
}
});
centerPane.add(GUICoreKit.createBorderLayoutPane(
typeComboBox, BorderLayout.WEST,
queryAllTextField, BorderLayout.CENTER,
execButton, BorderLayout.EAST
), BorderLayout.NORTH);
GridLayout gridLayout = new GridLayout(2, 1);
JPanel interactivePane = new JPanel(gridLayout);
centerPane.add(interactivePane, BorderLayout.CENTER);
consoleTextPane = new UISyntaxTextArea();
consoleTextPane.setEditable(false);
consoleTextPane.setText("{\n" +
" \"query\": {\n" +
" \"match_all\": {}\n" +
" }\n" +
"}");
interactivePane.add(createShowTextPane(consoleTextPane));
outputTextPane = new UISyntaxTextArea();
interactivePane.add(createShowTextPane(outputTextPane));
}
private void run() {
String connectionName = getSelectConnectionName();
final ElasticsearchConnection connection = ConnectionKit.getConnection(connectionName, ElasticsearchConnection.class);
if (connection != null) {
new SwingWorker<String, Void>() {
@Override
protected String doInBackground() {
String[] array = connection.summary(typeComboBox.getSelectedItem(), queryAllTextField.getText(), consoleTextPane.getText());
return ArrayKit.isEmpty(array) ? null : array[0];
}
@Override
protected void done() {
try {
String text = get();
outputTextPane.setText(text);
} catch (Exception e) {
LogKit.error(e.getMessage(), e);
}
}
}.execute();
}
}
private UISyntaxTextScrollPane createShowTextPane(UISyntaxTextArea consoleTextPane) {
consoleTextPane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT);
UISyntaxTextScrollPane sqlTextScrollPane = new UISyntaxTextScrollPane(consoleTextPane);
sqlTextScrollPane.setLineNumbersEnabled(false);
sqlTextScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC));
sqlTextScrollPane.setPreferredSize(new Dimension(300, 120));
return sqlTextScrollPane;
}
public String getSelectConnectionName() {
return connectionComboBoxPanel.getSelectedItem();
}
public void populateConnection(Connection connection) {
connectionComboBoxPanel.populate(connection);
}
@Override
protected String title4PopupWindow() {
return "Choose";
}
}

83
src/main/java/com/fr/plugin/db/es/ui/ElasticsearchConnectionPane.java

@ -1,9 +1,21 @@
package com.fr.plugin.db.es.ui;
import com.fanruan.api.design.DesignKit;
import com.fanruan.api.design.ui.component.UIButton;
import com.fanruan.api.design.ui.component.UILabel;
import com.fanruan.api.design.ui.component.UIPasswordField;
import com.fanruan.api.design.ui.component.UITextField;
import com.fanruan.api.design.ui.component.UITitledBorder;
import com.fanruan.api.design.ui.layout.TableLayoutKit;
import com.fanruan.api.design.util.GUICoreKit;
import com.fanruan.api.design.work.DatabaseConnectionPane;
import com.fanruan.api.util.IOKit;
import com.fr.plugin.db.es.fun.ElasticsearchConnection;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* @author richie
@ -12,23 +24,84 @@ import javax.swing.*;
*/
public class ElasticsearchConnectionPane extends DatabaseConnectionPane<ElasticsearchConnection> {
private UITextField hostTextField;
private UITextField portTextField;
private UITextField usernameTextField;
private UIPasswordField passwordTextField;
@Override
protected JPanel mainPanel() {
return null;
JPanel pane = new JPanel();
pane.setLayout(new BorderLayout());
hostTextField = new UITextField();
portTextField = new UITextField();
usernameTextField = new UITextField();
passwordTextField = new UIPasswordField();
JPanel globalConfigPane = new JPanel();
GridLayout gridLayout = new GridLayout(1, 2);
globalConfigPane.setLayout(gridLayout);
UIButton helpButton = new UIButton();
helpButton.setIcon(IOKit.readIcon("/com/fr/plugin/db/es/images/help.png"));
helpButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(
SwingUtilities.getWindowAncestor(ElasticsearchConnectionPane.this),
DesignKit.i18nText("Plugin-Elasticsearch_Host_Cluster_Description"),
DesignKit.i18nText("Plugin-Elasticsearch_Host_Cluster"),
JOptionPane.INFORMATION_MESSAGE
);
}
});
Component[][] components = new Component[][]{
{new UILabel(DesignKit.i18nText("Plugin-Elasticsearch_Host") + ":"),
GUICoreKit.createBorderLayoutPane(hostTextField, BorderLayout.CENTER, helpButton, BorderLayout.EAST)},
{new UILabel(DesignKit.i18nText("Plugin-Elasticsearch_Port") + ":"), portTextField},
{new UILabel(DesignKit.i18nText("Plugin-Elasticsearch_Username") + ":"), usernameTextField},
{new UILabel(DesignKit.i18nText("Plugin-Elasticsearch_Password") + ":"), passwordTextField},
};
double p = TableLayoutKit.PREFERRED;
double[] rowSize = new double[]{p, p, p, p, p};
double[] columnSize = new double[]{p, 400};
JPanel settingsUI = TableLayoutKit.createTableLayoutPane(components, rowSize, columnSize);
settingsUI.setBorder(UITitledBorder.createBorderWithTitle("Elasticsearch"));
JPanel centerPane = GUICoreKit.createNormalFlowInnerContainerPane();
centerPane.add(settingsUI);
pane.add(centerPane, BorderLayout.CENTER);
return pane;
}
@Override
protected void populateSubDatabaseConnectionBean(ElasticsearchConnection elasticsearchConnection) {
protected void populateSubDatabaseConnectionBean(ElasticsearchConnection connection) {
hostTextField.setText(connection.getHost());
portTextField.setText(connection.getPort());
usernameTextField.setText(connection.getUsername());
passwordTextField.setText(connection.getPassword());
}
@Override
protected ElasticsearchConnection updateSubDatabaseConnectionBean() {
return null;
ElasticsearchConnection connection = new ElasticsearchConnection();
connection.setHost(hostTextField.getText());
connection.setPort(portTextField.getText());
connection.setUsername(usernameTextField.getText());
connection.setPassword(passwordTextField.getText());
return connection;
}
@Override
protected String title4PopupWindow() {
return null;
return "Elasticsearch";
}
}

149
src/main/java/com/fr/plugin/db/es/ui/ElasticsearchQueryPane.java

@ -0,0 +1,149 @@
package com.fr.plugin.db.es.ui;
import com.fanruan.api.design.DesignKit;
import com.fanruan.api.design.macro.UIConstants;
import com.fanruan.api.design.ui.component.UIDictionaryComboBox;
import com.fanruan.api.design.ui.component.UILabel;
import com.fanruan.api.design.ui.component.UIRoundedBorder;
import com.fanruan.api.design.ui.component.UITextField;
import com.fanruan.api.design.ui.component.code.SyntaxConstants;
import com.fanruan.api.design.ui.component.code.UISyntaxTextArea;
import com.fanruan.api.design.ui.component.code.UISyntaxTextScrollPane;
import com.fanruan.api.design.ui.layout.TableLayoutKit;
import com.fr.design.dialog.BasicPane;
import com.fr.plugin.db.es.fun.ConfigAttribute;
import com.fr.plugin.db.es.fun.type.ConverterType;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
/**
* @author richie
* @version 10.0
* Created by richie on 2020/1/2
*/
public class ElasticsearchQueryPane extends BasicPane {
private UITextField endPointTextField;
private UIDictionaryComboBox<ConverterType> converterTypeComboBox;
private UISyntaxTextArea queryTextPane;
private UISyntaxTextArea scriptTextPane;
private UIDictionaryComboBox<Boolean> sortedComboBox;
private UIDictionaryComboBox<Boolean> prepareComboBox;
@Override
protected String title4PopupWindow() {
return "JSON Query";
}
public ElasticsearchQueryPane() {
setLayout(new BorderLayout());
double p = TableLayoutKit.PREFERRED;
double f = TableLayoutKit.FILL;
double[] rowSize = {p, p, p, p, p, p};
double[] columnSize = {p, f};
endPointTextField = new UITextField();
queryTextPane = new UISyntaxTextArea();
converterTypeComboBox = new UIDictionaryComboBox<>(new ConverterType[]{
ConverterType.JSON,
ConverterType.JS
}, new String[]{
DesignKit.i18nText("Plugin-Elasticsearch_Auto"),
DesignKit.i18nText("Plugin-Elasticsearch_Program")
});
converterTypeComboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
checkEnabled();
}
});
scriptTextPane = new UISyntaxTextArea();
sortedComboBox = new UIDictionaryComboBox<>(
new Boolean[]{false, true},
new String[]{DesignKit.i18nText("Plugin-Elasticsearch_Sort_Default"), com.fr.design.i18n.Toolkit.i18nText("Plugin-JSON_Sort_Open")});
prepareComboBox = new UIDictionaryComboBox<>(
new Boolean[]{false, true},
new String[]{DesignKit.i18nText("Plugin-Elasticsearch_Prepare_Keys_Default"), com.fr.design.i18n.Toolkit.i18nText("Plugin-JSON_Prepare_Keys_Open")}
);
Component[][] coms = new Component[][]{
{new UILabel(DesignKit.i18nText("Plugin-Elasticsearch_Endpoint") + ":"), endPointTextField},
{new UILabel(DesignKit.i18nText("Plugin-Elasticsearch_Query") + ":"), createConditionTextPane(queryTextPane)},
{new UILabel(DesignKit.i18nText("Plugin-Elasticsearch_Result_Type")+ ":"), converterTypeComboBox},
{new UILabel(DesignKit.i18nText("Plugin-Elasticsearch_Result_Script")+ ":"), createConditionTextPane(scriptTextPane)},
{new UILabel(DesignKit.i18nText("Plugin-Elasticsearch_Sort_Key") + ":"), sortedComboBox},
{new UILabel(DesignKit.i18nText("Plugin-Elasticsearch_Key_Prepare") + ":"), prepareComboBox}
};
JPanel panel = TableLayoutKit.createTableLayoutPane(coms, rowSize, columnSize);
add(panel, BorderLayout.CENTER);
}
private UISyntaxTextScrollPane createConditionTextPane(UISyntaxTextArea sqlTextPane) {
sqlTextPane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT);
UISyntaxTextScrollPane sqlTextScrollPane = new UISyntaxTextScrollPane(sqlTextPane);
sqlTextScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC));
sqlTextScrollPane.setPreferredSize(new Dimension(680, 120));
return sqlTextScrollPane;
}
private void checkEnabled() {
ConverterType converterType = getConverterType();
sortedComboBox.setEnabled(converterType == ConverterType.JSON);
prepareComboBox.setEnabled(converterType == ConverterType.JSON);
}
public String getEndPoint() {
return endPointTextField.getText();
}
public void setEndPoint(String endPoint) {
endPointTextField.setText(endPoint);
}
public ConverterType getConverterType() {
return converterTypeComboBox.getSelectedItem();
}
public void setConverterTypeComboBox(ConverterType converterType) {
converterTypeComboBox.setSelectedItem(converterType);
}
public String getQuery() {
return queryTextPane.getText();
}
public void setQuery(String query) {
queryTextPane.setText(query);
}
public String getScript() {
return scriptTextPane.getText();
}
public void setScript(String script) {
scriptTextPane.setText(script);
}
public ConfigAttribute getConfigAttr() {
ConfigAttribute attr = new ConfigAttribute();
attr.setSorted(sortedComboBox.getSelectedItem());
attr.setPrepare(prepareComboBox.getSelectedItem());
return attr;
}
public void setConfigAttr(ConfigAttribute attr) {
if (attr == null) {
return;
}
sortedComboBox.setSelectedItem(attr.isSorted());
prepareComboBox.setSelectedItem(attr.isPrepare());
}
}

173
src/main/java/com/fr/plugin/db/es/ui/ElasticsearchTableDataPane.java

@ -1,7 +1,26 @@
package com.fr.plugin.db.es.ui;
import com.fanruan.api.cal.ParameterKit;
import com.fanruan.api.data.ConnectionKit;
import com.fanruan.api.design.DesignKit;
import com.fanruan.api.design.ui.action.UpdateAction;
import com.fanruan.api.design.ui.component.UIToolbar;
import com.fanruan.api.design.ui.component.table.UITableEditorPane;
import com.fanruan.api.design.ui.component.table.action.UITableEditAction;
import com.fanruan.api.design.ui.component.table.model.ParameterTableModel;
import com.fanruan.api.design.ui.toolbar.ToolBarDef;
import com.fanruan.api.design.work.BaseTableDataPane;
import com.fanruan.api.util.ArrayKit;
import com.fanruan.api.util.IOKit;
import com.fanruan.api.util.StringKit;
import com.fr.plugin.db.es.fun.ElasticsearchTableData;
import com.fr.script.Calculator;
import com.fr.stable.ParameterProvider;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
/**
* @author richie
@ -10,18 +29,164 @@ import com.fr.plugin.db.es.fun.ElasticsearchTableData;
*/
public class ElasticsearchTableDataPane extends BaseTableDataPane<ElasticsearchTableData> {
@Override
public void populateBean(ElasticsearchTableData elasticsearchTableData) {
private static final String PREVIEW_BUTTON = DesignKit.i18nText("Plugin-Elasticsearch_Preview");
private static final String REFRESH_BUTTON = DesignKit.i18nText("Plugin-Elasticsearch_Refresh");
private ElasticsearchConnectionChosePane chosePane;
private UITableEditorPane<ParameterProvider> editorPane;
private ElasticsearchQueryPane queryPane;
public ElasticsearchTableDataPane() {
this.setLayout(new BorderLayout(4, 4));
Box box = new Box(BoxLayout.Y_AXIS);
JPanel northPane = new JPanel(new BorderLayout(4, 4));
JToolBar editToolBar = createToolBar();
northPane.add(editToolBar, BorderLayout.CENTER);
northPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 6, 0));
ParameterTableModel model = new ParameterTableModel() {
@Override
public UITableEditAction[] createAction() {
return ArrayKit.add(
super.createAction(),
new RefreshAction());
}
};
editorPane = new UITableEditorPane<>(model);
box.add(northPane);
addQueryPane(box);
box.add(editorPane);
JPanel sqlSplitPane = new JPanel(new BorderLayout(4, 4));
sqlSplitPane.add(box, BorderLayout.CENTER);
chosePane = new ElasticsearchConnectionChosePane();
chosePane.setPreferredSize(new Dimension(300, 200));
sqlSplitPane.add(chosePane, BorderLayout.WEST);
this.add(sqlSplitPane, BorderLayout.CENTER);
}
private void addQueryPane(Box box) {
queryPane = new ElasticsearchQueryPane();
box.add(queryPane);
}
private JToolBar createToolBar() {
ToolBarDef toolBarDef = new ToolBarDef();
toolBarDef.addShortCut(new PreviewAction());
UIToolbar editToolBar = ToolBarDef.createJToolBar();
toolBarDef.updateToolBar(editToolBar);
return editToolBar;
}
private class PreviewAction extends UpdateAction {
public PreviewAction() {
this.setName(PREVIEW_BUTTON);
this.setMnemonic('P');
this.setSmallIcon(IOKit.readIcon("/com/fr/plugin/db/es/images/preview.png"));
}
public void actionPerformed(ActionEvent evt) {
checkParameter();
DesignKit.previewTableData(ElasticsearchTableDataPane.this.updateBean());
}
}
protected class RefreshAction extends UITableEditAction {
public RefreshAction() {
this.setName(REFRESH_BUTTON);
this.setSmallIcon(IOKit.readIcon("/com/fr/plugin/db/es/images/refresh.png"));
}
public void actionPerformed(ActionEvent e) {
refresh();
}
@Override
public void checkEnabled() {
}
}
private String[] parameterTextSource() {
return new String[]{
queryPane.getQuery(), queryPane.getEndPoint(), queryPane.getScript()
};
}
private void refresh() {
String[] paramTexts = parameterTextSource();
java.util.List<ParameterProvider> existParameterList = editorPane.update();
ParameterProvider[] ps = existParameterList == null ? new ParameterProvider[0] : existParameterList.toArray(new ParameterProvider[0]);
editorPane.populate(ParameterKit.analyzeAndUnionSameParameters(paramTexts, ps));
}
private void checkParameter() {
String[] paramTexts = parameterTextSource();
ParameterProvider[] parameters = ParameterKit.analyze4Parameters(paramTexts, false);
if (parameters.length < 1 && editorPane.update().size() < 1) {
return;
}
boolean isIn = true;
java.util.List<ParameterProvider> list = editorPane.update();
java.util.List<String> name = new ArrayList<String>();
for (int i = 0; i < list.size(); i++) {
name.add(list.get(i).getName());
}
for (int i = 0; i < parameters.length; i++) {
if (!name.contains(parameters[i].getName())) {
isIn = false;
break;
}
}
if (list.size() == parameters.length && isIn) {
return;
}
refresh();
}
@Override
public void populateBean(ElasticsearchTableData tableData) {
if (tableData == null) {
return;
}
chosePane.populateConnection(tableData.getDatabase());
editorPane.populate(tableData.getParameters(Calculator.createCalculator()));
queryPane.setEndPoint(tableData.getEndPoint());
queryPane.setConfigAttr(tableData.getConfigAttribute());
queryPane.setQuery(tableData.getQuery());
queryPane.setConverterTypeComboBox(tableData.getConverterType());
queryPane.setScript(tableData.getScript());
}
@Override
public ElasticsearchTableData updateBean() {
return null;
ElasticsearchTableData tableData = new ElasticsearchTableData();
String name = chosePane.getSelectConnectionName();
if (StringKit.isNotEmpty(name)) {
tableData.setDatabase(ConnectionKit.createNameConnection(name));
}
java.util.List<ParameterProvider> providerList = editorPane.update();
tableData.setParameters(providerList.toArray(new ParameterProvider[0]));
tableData.setEndPoint(queryPane.getEndPoint());
tableData.setQuery(queryPane.getQuery());
tableData.setConverterType(queryPane.getConverterType());
tableData.setConfigAttribute(queryPane.getConfigAttr());
tableData.setScript(queryPane.getScript());
return tableData;
}
@Override
protected String title4PopupWindow() {
return null;
return DesignKit.i18nText("Plugin_Elasticsearch_Table_Data");
}
}

BIN
src/main/resources/com/fr/plugin/db/es/images/help.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 817 B

BIN
src/main/resources/com/fr/plugin/db/es/images/preview.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

BIN
src/main/resources/com/fr/plugin/db/es/images/refresh.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save