增强公式编辑器,能让公式支持脚本和实时计算。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

307 lines
12 KiB

package com.fr.solution.plugin.design.formula.compat;
import com.fanruan.api.function.FunctionKit;
import com.fanruan.api.log.LogKit;
import com.fanruan.api.macro.EncodeConstants;
import com.fanruan.api.util.GeneralKit;
import com.fanruan.api.util.OperatingKit;
import com.fanruan.api.util.StringKit;
import com.fanruan.api.util.TypeKit;
import com.fr.design.formula.FunctionGroup;
import com.fr.design.formula.NameAndDescription;
import com.fr.function.AVERAGE;
import com.fr.function.CHAR;
import com.fr.function.COUNT;
import com.fr.function.DATE;
import com.fr.function.MAX;
import com.fr.function.MIN;
import com.fr.function.RANGE;
import com.fr.function.SUM;
import com.fr.function.TIME;
import com.fr.plugin.ExtraClassManager;
import com.fr.stable.fun.FunctionDefContainer;
import com.fr.stable.fun.mark.Mutable;
import com.fr.stable.script.Function;
import com.fr.stable.script.FunctionDef;
import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* @author richie
* @version 10.0
* Created by richie on 2019-02-27
*/
public final class FunctionConstants {
public static FunctionGroup PLUGIN = getPluginFunctionGroup();
public static FunctionGroup CUSTOM = getCustomFunctionGroup();
public static NameAndFunctionList COMMON = getCommonFunctionList();
public static NameAndTypeAndFunctionList[] EMBFUNCTIONS = getEmbededFunctionListArray();
public static FunctionGroup ALL = getAllFunctionGroup();
static {
loadEmbededFunctions();
}
/**
* Don't let anyone instantiate this class.
*/
private FunctionConstants() {
}
private static void loadEmbededFunctions() {
String pkgName = "com.fr.function";
Class<Function> iface = Function.class;
ClassLoader classloader = iface.getClassLoader();
Enumeration<URL> urlEnumeration = null;
try {
urlEnumeration = classloader.getResources(pkgName.replace('.', '/'));
} catch (IOException e) {
LogKit.error(e.getMessage());
return;
}
while (urlEnumeration.hasMoreElements()) {
URL url = urlEnumeration.nextElement();
String classFilePath = url.getFile();
/*
* alex:url.getFile获取的地址中,如果有空格或中文会被URLEncoder.encode处理
* 会变成%20这种%打头的东西,但是new File的时候%20是无法解析成空格,所以在此需要做URLDecoder.decode处理
*/
try {
classFilePath = URLDecoder.decode(classFilePath, EncodeConstants.ENCODING_UTF_8);
} catch (UnsupportedEncodingException e1) {
LogKit.error(e1.getMessage(), e1);
}
LogKit.info("ClassFilePath:" + classFilePath);
if (isCustomFormulaPath(classFilePath)) {
continue;
}
for (String fileName : findClassNamesUnderFilePath(classFilePath)) {
try {
Class<?> cls = Class.forName(pkgName + "." + fileName.substring(0, fileName.length() - 6));
if (TypeKit.classInstanceOf(cls, iface)) {
Function inst;
inst = (Function) cls.newInstance();
for (NameAndTypeAndFunctionList EMBFUNCTION : EMBFUNCTIONS) {
if (EMBFUNCTION.test(inst)) {
break;
}
}
}
} catch (Exception ignore) {
} catch (Throwable e) {
// 不要因为个别公式加载失败,而导致整个函数面板无法启动
LogKit.error(e.getMessage());
}
}
}
}
private static boolean isCustomFormulaPath(String classFilePath) {
return !isJarPath(classFilePath) && isNotDebugMode();
}
private static boolean isNotDebugMode() {
return GeneralKit.readBuildNO().contains("-");
}
private static boolean isJarPath(String classFilePath) {
return classFilePath.contains("!/");
}
/**
* 将函数分组插件中的函数添加到对应的列表中
*
* @param listModel
*/
public static void addFunctionGroupFromPlugins(DefaultListModel listModel) {
//hugh:自定义函数分组
Set<Mutable> containers = ExtraClassManager.getInstance().getArray(FunctionDefContainer.MARK_STRING);
if (!containers.isEmpty()) {
for (Mutable container : containers) {
listModel.addElement(createFunctionGroup((FunctionDefContainer) container));
}
}
}
/**
* 创建一个新的分组
*
* @param container
* @return
*/
private static FunctionGroup createFunctionGroup(final FunctionDefContainer container) {
return new FunctionGroup() {
@Override
public String getGroupName() {
return container.getGroupName();
}
@Override
public NameAndDescription[] getDescriptions() {
FunctionDef[] fs = container.getFunctionDefs();
int count = fs.length;
FunctionDefNAD[] nads = new FunctionDefNAD[count];
for (int i = 0; i < count; i++) {
nads[i] = new FunctionDefNAD(fs[i]);
}
return nads;
}
};
}
private static String[] findClassNamesUnderFilePath(String filePath) {
java.util.List<String> classNameList = new ArrayList<String>();
if (isJarPath(filePath)) {
String[] arr = filePath.split("!/");
String jarPath = arr[0].substring(6);
String classPath = arr[1];
if (classPath.endsWith("/")) {
classPath = classPath.substring(0, classPath.length() - 1);
}
if (!OperatingKit.isWindows()) {
//windows里substring后是d:\123\456, mac下substring后是Application/123/456
jarPath = StringKit.perfectStart(jarPath, "/");
}
ZipFile zip;
try {
zip = new ZipFile(jarPath);
Enumeration entries = zip.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
if (entry.isDirectory()) {
continue;
}
String entryName = entry.getName();
if (!entryName.contains(classPath) || !entryName.endsWith(".class")) {
continue;
}
classNameList.add(entryName.substring(classPath.length() + 1));
}
} catch (IOException e) {
LogKit.error(e.getMessage(), e);
}
} else {
File dir = new File(filePath);
File[] files = dir.listFiles();
if (files != null) {
for (File f : files) {
String fileName = f.getName();
if (fileName.endsWith(".class")) {
classNameList.add(fileName);
}
}
}
}
return classNameList.toArray(new String[0]);
}
private static FunctionGroup getPluginFunctionGroup() {
return new FunctionGroup() {
@Override
public String getGroupName() {
return DesignToolkit.getLocText("Plugin-Design_Basic_Base_Formula_Plugin");
}
@Override
public NameAndDescription[] getDescriptions() {
FunctionDef[] fs = ExtraClassManager.getInstance().getFunctionDef();
int count = fs.length;
FunctionDefNAD[] nads = new FunctionDefNAD[count];
for (int i = 0; i < count; i++) {
nads[i] = new FunctionDefNAD(fs[i]);
}
return nads;
}
};
}
private static FunctionGroup getCustomFunctionGroup() {
return new FunctionGroup() {
@Override
public String getGroupName() {
return DesignToolkit.getLocText("Plugin-Design_Basic_FormulaD_Custom_Function");
}
@Override
public NameAndDescription[] getDescriptions() {
return FunctionKit.getDescription();
}
};
}
private static NameAndFunctionList getCommonFunctionList() {
return new NameAndFunctionList(DesignToolkit.getLocText("Plugin-Design_Basic_FormulaD_Most_Recently_Used"), new Function[]{
new SUM(), new COUNT(), new AVERAGE(), new CHAR(), new DATE(), new MAX(), new MIN(), new TIME(), new RANGE()
});
}
private static NameAndTypeAndFunctionList[] getEmbededFunctionListArray() {
return new NameAndTypeAndFunctionList[]{
new NameAndTypeAndFunctionList(DesignToolkit.getLocText("Plugin-Design_Basic_FormulaD_Math_&_Trig"), Function.MATH),
new NameAndTypeAndFunctionList(DesignToolkit.getLocText("Plugin-Design_Basic_FormulaD_Text"), Function.TEXT),
new NameAndTypeAndFunctionList(DesignToolkit.getLocText("Plugin-Design_Basic_FormulaD_Date_&_Time"), Function.DATETIME),
new NameAndTypeAndFunctionList(DesignToolkit.getLocText("Plugin-Design_Basic_FormulaD_Logical"), Function.LOGIC),
new NameAndTypeAndFunctionList(DesignToolkit.getLocText("Plugin-Design_Basic_FormulaD_Array"), Function.ARRAY),
new NameAndTypeAndFunctionList(DesignToolkit.getLocText("Plugin-Design_Basic_FormulaD_Report"), Function.REPORT),
new NameAndTypeAndFunctionList(DesignToolkit.getLocText("Plugin-Design_Basic_FormulaD_Other"), Function.OTHER),
new NameAndTypeAndFunctionList(DesignToolkit.getLocText("Plugin-Design_Basic_Function_Type_Hierarchy"), Function.HA)
};
}
private static FunctionGroup getAllFunctionGroup() {
return new FunctionGroup() {
@Override
public String getGroupName() {
return DesignToolkit.getLocText("Plugin-Design_Basic_FormulaD_All");
}
@Override
public NameAndDescription[] getDescriptions() {
List<NameAndDescription> all = new ArrayList<NameAndDescription>();
for (int i = 0; i < EMBFUNCTIONS.length; i++) {
all.addAll(Arrays.asList(EMBFUNCTIONS[i].getDescriptions()));
}
Collections.addAll(all, PLUGIN.getDescriptions());
Collections.addAll(all, CUSTOM.getDescriptions());
//hugh:自定义函数分组
Set<Mutable> containers = ExtraClassManager.getInstance().getArray(FunctionDefContainer.MARK_STRING);
if (!containers.isEmpty()) {
for (Mutable container : containers) {
Collections.addAll(all, createFunctionGroup(((FunctionDefContainer) container)).getDescriptions());
}
}
Collections.sort(all, new Comparator<NameAndDescription>() {
@Override
public int compare(NameAndDescription o1, NameAndDescription o2) {
return GeneralKit.compare(o1.getName(), o2.getName());
}
});
return all.toArray(new NameAndDescription[0]);
}
};
}
}