diff --git a/designer-base/src/main/java/com/fr/design/formula/FunctionConstants.java b/designer-base/src/main/java/com/fr/design/formula/FunctionConstants.java index 0abc2f46e..750df1bad 100644 --- a/designer-base/src/main/java/com/fr/design/formula/FunctionConstants.java +++ b/designer-base/src/main/java/com/fr/design/formula/FunctionConstants.java @@ -35,13 +35,75 @@ import java.util.zip.ZipFile; import javax.swing.DefaultListModel; -public abstract class FunctionConstants { - +public final class FunctionConstants { + + public static FunctionGroup PLUGIN = getPluginFunctionGroup(); + public static FunctionGroup CUSTOM = getCustomFunctionGroup(); + static NameAndFunctionList COMMON = getCommonFunctionList(); + 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 iface = Function.class; + ClassLoader classloader = iface.getClassLoader(); + Enumeration urlEnumeration = null; + try { + urlEnumeration = classloader.getResources(pkgName.replace('.', '/')); + } catch (IOException e) { + FineLoggerFactory.getLogger().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) { + FRContext.getLogger().error(e1.getMessage(), e1); + } + FRContext.getLogger().info("ClassFilePath:" + classFilePath); + /* + * alex:如果是jar包中的class文件 + * file:/D:/opt/FineReport6.5/WebReport/WEB-INF/lib/fr-server-6.5.jar!/com/fr/rpt/script/function + */ + for (String fileName : findClassNamesUnderFilePath(classFilePath)) { + try { + Class cls = Class.forName(pkgName + "." + fileName.substring(0, fileName.length() - 6)); + if (StableUtils.classInstanceOf(cls, iface)) { + Function inst; + inst = (Function)cls.newInstance(); + for (NameAndTypeAndFunctionList EMBFUNCTION : EMBFUNCTIONS) { + if (EMBFUNCTION.test(inst)) { + break; + } + } + } + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException ignore) { + } + } + } + } + /** * 将函数分组插件中的函数添加到对应的列表中 * @param listModel */ - public static void addFunctionGroupFromPlugins(DefaultListModel listModel){ + static void addFunctionGroupFromPlugins(DefaultListModel listModel){ //hugh:自定义函数分组 Set containers = ExtraClassManager.getInstance().getArray(FunctionDefContainer.MARK_STRING); if(!containers.isEmpty()){ @@ -75,107 +137,15 @@ public abstract class FunctionConstants { } }; } - - public static FunctionGroup PLUGIN = new FunctionGroup() { - @Override - public String getGroupName() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-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; - } - }; - - public static FunctionGroup CUSTOM = new FunctionGroup() { - @Override - public String getGroupName() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Custom_Function"); - } - - @Override - public NameAndDescription[] getDescriptions() { - FunctionConfig funtionManager = FunctionConfig.getInstance(); - if (funtionManager != null) { - int functionDefCount = funtionManager.getFunctionDefCount(); - - FunctionDefNAD[] nads = new FunctionDefNAD[functionDefCount]; - for (int i = 0; i < functionDefCount; i++) { - nads[i] = new FunctionDefNAD(funtionManager.getFunctionDef(i)); - } - - return nads; - } - - return new NameAndDescription[0]; - } - }; - - public static NameAndFunctionList COMMON = new NameAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-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() - }); - - public static NameAndTypeAndFunctionList[] EMBFUNCTIONS = new NameAndTypeAndFunctionList[] { - new NameAndTypeAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Math_&_Trig"), Function.MATH), - new NameAndTypeAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Text"), Function.TEXT), - new NameAndTypeAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Date_&_Time"), Function.DATETIME), - new NameAndTypeAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Logical"), Function.LOGIC), - new NameAndTypeAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Array"), Function.ARRAY), - new NameAndTypeAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Report"), Function.REPORT), - new NameAndTypeAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Other"), Function.OTHER), - new NameAndTypeAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Function_Type_Hierarchy"), Function.HA) - }; - - public static FunctionGroup ALL = new FunctionGroup() { - @Override - public String getGroupName() { - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_All"); - } - - @Override - public NameAndDescription[] getDescriptions() { - List all = new ArrayList(); - 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 containers = ExtraClassManager.getInstance().getArray(FunctionDefContainer.MARK_STRING); - if(!containers.isEmpty()){ - for(Mutable container : containers){ - Collections.addAll(all,createFunctionGroup(((FunctionDefContainer)container)).getDescriptions()); - } - } - java.util.Collections.sort(all, NameAndDescriptionComparator); - - return all.toArray(new NameAndDescription[all.size()]); - } - }; - - private static Comparator NameAndDescriptionComparator = new Comparator() { - @Override - public int compare(NameAndDescription o1, NameAndDescription o2) { - return ComparatorUtils.compare(o1.getName(), o2.getName()); - } - }; - private static String[] findClassNamesUnderFilePath(String filePath) { java.util.List classNameList = new ArrayList(); /* * alex:如果是jar包中的class文件 * file:/D:/opt/FineReport6.5/WebReport/WEB-INF/lib/fr-server-6.5.jar!/com/fr/rpt/script/function */ - if (filePath.indexOf("!/") >= 0) { + if (filePath.contains("!/")) { String[] arr = filePath.split("!/"); String jarPath = arr[0].substring(6); // alex:substring(6)去掉前面的file:/这六个字符 String classPath = arr[1]; @@ -198,7 +168,7 @@ public abstract class FunctionConstants { } String entryName = entry.getName(); - if (entryName.indexOf(classPath) < 0 || !entryName.endsWith(".class")) { + if (!entryName.contains(classPath) || !entryName.endsWith(".class")) { continue; } @@ -209,66 +179,117 @@ public abstract class FunctionConstants { } } else { File dir = new File(filePath); - - for (File f : dir.listFiles()) { - String fileName = f.getName(); - if (fileName.endsWith(".class")) { - classNameList.add(fileName); + 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[classNameList.size()]); + return classNameList.toArray(new String[0]); } - - // alex:读取com.fr.script.function包下面所有的Function类 - static { - String pkgName = "com.fr.function"; - Class iface = Function.class; - ClassLoader classloader = iface.getClassLoader(); - Enumeration urlEnumeration = null; - try { - urlEnumeration = classloader.getResources(pkgName.replace('.', '/')); - } catch (IOException e) { - FineLoggerFactory.getLogger().error(e.getMessage()); - } - 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) { - FRContext.getLogger().error(e1.getMessage(), e1); + private static FunctionGroup getPluginFunctionGroup() { + return new FunctionGroup() { + @Override + public String getGroupName() { + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Base_Formula_Plugin"); } - FRContext.getLogger().info("ClassFilePath:" + classFilePath); - /* - * alex:如果是jar包中的class文件 - * file:/D:/opt/FineReport6.5/WebReport/WEB-INF/lib/fr-server-6.5.jar!/com/fr/rpt/script/function - */ - for (String fileName : findClassNamesUnderFilePath(classFilePath)) { - try { - Class cls = Class.forName(pkgName + "." + fileName.substring(0, fileName.length() - 6)); - System.out.println(pkgName + "." + fileName.substring(0, fileName.length() - 6)); - if (StableUtils.classInstanceOf(cls, iface)) { - Function inst; - inst = (Function)cls.newInstance(); - for (int fi = 0; fi < EMBFUNCTIONS.length; fi++) { - if (EMBFUNCTIONS[fi].test(inst)) { - break; - } - } + @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 com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Custom_Function"); + } + + @Override + public NameAndDescription[] getDescriptions() { + FunctionConfig funtionManager = FunctionConfig.getInstance(); + if (funtionManager != null) { + int functionDefCount = funtionManager.getFunctionDefCount(); + + FunctionDefNAD[] nads = new FunctionDefNAD[functionDefCount]; + for (int i = 0; i < functionDefCount; i++) { + nads[i] = new FunctionDefNAD(funtionManager.getFunctionDef(i)); + } + + return nads; + } + + return new NameAndDescription[0]; + } + }; + } + + private static NameAndFunctionList getCommonFunctionList() { + return new NameAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-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(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Math_&_Trig"), Function.MATH), + new NameAndTypeAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Text"), Function.TEXT), + new NameAndTypeAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Date_&_Time"), Function.DATETIME), + new NameAndTypeAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Logical"), Function.LOGIC), + new NameAndTypeAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Array"), Function.ARRAY), + new NameAndTypeAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Report"), Function.REPORT), + new NameAndTypeAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_Other"), Function.OTHER), + new NameAndTypeAndFunctionList(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Function_Type_Hierarchy"), Function.HA) + }; + } + + private static FunctionGroup getAllFunctionGroup() { + return new FunctionGroup() { + @Override + public String getGroupName() { + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_FormulaD_All"); + } + + @Override + public NameAndDescription[] getDescriptions() { + List all = new ArrayList(); + 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 containers = ExtraClassManager.getInstance().getArray(FunctionDefContainer.MARK_STRING); + if(!containers.isEmpty()){ + for(Mutable container : containers){ + Collections.addAll(all,createFunctionGroup(((FunctionDefContainer)container)).getDescriptions()); } - } catch (ClassNotFoundException e) { - } catch (InstantiationException e) { - } catch (IllegalAccessException e) { } + + Collections.sort(all, new Comparator() { + @Override + public int compare(NameAndDescription o1, NameAndDescription o2) { + return ComparatorUtils.compare(o1.getName(), o2.getName()); + } + }); + + return all.toArray(new NameAndDescription[0]); } - } + }; } } diff --git a/designer-base/src/test/java/com/fr/design/formula/FunctionConstantsTest.java b/designer-base/src/test/java/com/fr/design/formula/FunctionConstantsTest.java new file mode 100644 index 000000000..33cfd577d --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/formula/FunctionConstantsTest.java @@ -0,0 +1,40 @@ +package com.fr.design.formula; + +import org.junit.Test; + +import static junit.framework.Assert.fail; +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertTrue; + +/** + * Created by plough on 2018/12/7. + */ +public class FunctionConstantsTest { + @Test + public void testNewInstanceFail() throws Exception { + try { + FunctionConstants.class.newInstance(); + fail("Not allowed to instantiate FunctionConstants!"); + } catch (IllegalAccessException e) { + assertTrue(true); + } + } + + @Test + public void testEmbedFuntionsAfterStaticInit() { + NameAndTypeAndFunctionList[] embFunctionLists = FunctionConstants.EMBFUNCTIONS; + // 一共有 8 个分类 + assertEquals(8, embFunctionLists.length); + for (NameAndTypeAndFunctionList embFunctionsList : embFunctionLists) { + // 每个分类下都有函数 + NameAndDescription[] nameAndDescriptions = embFunctionsList.getDescriptions(); + assertTrue(nameAndDescriptions.length > 0); + } + } + + @Test + public void testCommonFuntionsAfterStaticInit() { + NameAndFunctionList commonFunctionList = FunctionConstants.COMMON; + assertEquals(9, commonFunctionList.getDescriptions().length); + } +}