From 8c200726ca220c9776f25bbac96c6aaa186a25b8 Mon Sep 17 00:00:00 2001 From: Hoky <303455184@qq.com> Date: Tue, 28 Sep 2021 15:11:07 +0800 Subject: [PATCH 1/3] =?UTF-8?q?REPORT-54887=20=E5=85=AC=E5=BC=8F=E7=BC=96?= =?UTF-8?q?=E8=BE=91=E5=99=A8=E4=BC=98=E5=8C=96=E4=B8=80=E6=9C=9F=201.?= =?UTF-8?q?=E6=8F=90=E4=BE=9B=E4=B8=80=E4=B8=AA=E5=85=AC=E5=BC=8F=E6=A3=80?= =?UTF-8?q?=E9=AA=8C=E7=9A=84=E6=8E=A5=E5=8F=A3=EF=BC=8C=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E4=BF=A1=E6=81=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/fr/design/formula/FormulaChecker.java | 88 +++++++++++++++++++ .../com/fr/design/formula/FormulaPane.java | 74 +--------------- 2 files changed, 91 insertions(+), 71 deletions(-) create mode 100644 designer-base/src/main/java/com/fr/design/formula/FormulaChecker.java diff --git a/designer-base/src/main/java/com/fr/design/formula/FormulaChecker.java b/designer-base/src/main/java/com/fr/design/formula/FormulaChecker.java new file mode 100644 index 000000000..093f26edf --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/formula/FormulaChecker.java @@ -0,0 +1,88 @@ +package com.fr.design.formula; + +import com.fr.design.i18n.Toolkit; +import com.fr.log.FineLoggerFactory; +import com.fr.parser.FRLexer; +import com.fr.parser.FRParser; +import com.fr.script.checker.FunctionCheckerDispatcher; +import com.fr.script.checker.exception.ConditionCheckWrongException; +import com.fr.script.checker.exception.FunctionCheckWrongException; +import com.fr.script.rules.FunctionParameterType; +import com.fr.script.rules.FunctionRule; +import com.fr.stable.StringUtils; +import com.fr.stable.script.Expression; +import com.fr.stable.script.Node; + +import java.io.StringReader; +import java.util.List; + +/** + * @author Hoky + * @date 2021/9/28 + */ +public class FormulaChecker { + private static final String VALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Valid_Formula"); + private static final String INVALID_FORMULA = Toolkit.i18nText("Fine-Design_Basic_FormulaD_Invalid_Formula"); + public static final String COLON = ":"; + + public static String check(String formulaText) { + StringReader in = new StringReader(formulaText); + + FRLexer lexer = new FRLexer(in); + FRParser parser = new FRParser(lexer); + + try { + Expression expression = parser.parse(); + Node node = expression.getConditionalExpression(); + return FunctionCheckerDispatcher.getInstance() + .getFunctionChecker(node) + .checkFunction(node) ? VALID_FORMULA : INVALID_FORMULA; + } catch (ConditionCheckWrongException cce) { + String functionName = cce.getFunctionName(); + return functionName + Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Condition_Tips") + COLON; + } catch (FunctionCheckWrongException ce) { + List rules = ce.getRules(); + String functionName = ce.getFunctionName(); + StringBuilder errorMsg = new StringBuilder(functionName + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Error_Tips") + COLON); + for (int i = 0; i < rules.size(); i++) { + errorMsg.append("("); + if (rules.get(i).getParameterList().isEmpty()) { + errorMsg.append(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_No_Param")); + } + for (FunctionParameterType functionParameterType : rules.get(i).getParameterList()) { + errorMsg.append(getTypeString(functionParameterType)).append(","); + } + if (",".equals(errorMsg.charAt(errorMsg.length() - 1) + "")) { + errorMsg.deleteCharAt(errorMsg.length() - 1); + } + errorMsg.append(")"); + if (i != rules.size() - 1) { + errorMsg.append(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Or")); + } + } + return errorMsg.toString(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return INVALID_FORMULA; + // alex:继续往下面走,expression为null时告知不合法公式 + } + } + + private static String getTypeString(FunctionParameterType type) { + switch (type) { + case NUMBER: + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Number"); + case STRING: + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_String"); + case ANY: + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Any"); + case DATE: + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Date"); + case BOOLEAN: + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Boolean"); + case ARRAY: + return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Array"); + } + return StringUtils.EMPTY; + } +} diff --git a/designer-base/src/main/java/com/fr/design/formula/FormulaPane.java b/designer-base/src/main/java/com/fr/design/formula/FormulaPane.java index 52807a6cb..608e8e684 100644 --- a/designer-base/src/main/java/com/fr/design/formula/FormulaPane.java +++ b/designer-base/src/main/java/com/fr/design/formula/FormulaPane.java @@ -38,18 +38,11 @@ import com.fr.log.FineLoggerFactory; import com.fr.parser.ArrayExpression; import com.fr.parser.BlockIntervalLiteral; import com.fr.parser.ColumnRowRangeInPage; -import com.fr.parser.FRLexer; -import com.fr.parser.FRParser; import com.fr.parser.NumberLiteral; import com.fr.parser.SheetIntervalLiteral; import com.fr.report.core.namespace.SimpleCellValueNameSpace; import com.fr.script.Calculator; import com.fr.script.ScriptConstants; -import com.fr.script.checker.FunctionCheckerDispatcher; -import com.fr.script.checker.exception.ConditionCheckWrongException; -import com.fr.script.checker.exception.FunctionCheckWrongException; -import com.fr.script.rules.FunctionParameterType; -import com.fr.script.rules.FunctionRule; import com.fr.stable.EncodeConstants; import com.fr.stable.EssentialUtils; import com.fr.stable.ParameterProvider; @@ -657,7 +650,7 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { public void actionPerformed(ActionEvent evt) { // Execute Formula default cell element. String formulaText = formulaTextArea.getText().trim(); - String formulaValidMessage = getFormulaValidMessage(formulaText); + String formulaValidMessage = FormulaChecker.check(formulaText); FineJOptionPane.showMessageDialog( FormulaPane.this, formulaValidMessage + ".", @@ -666,73 +659,12 @@ public class FormulaPane extends BasicPane implements KeyListener, UIFormula { } }; - private static String getFormulaValidMessage(String formulaText) { - StringReader in = new StringReader(formulaText); - - FRLexer lexer = new FRLexer(in); - FRParser parser = new FRParser(lexer); - - try { - Expression expression = parser.parse(); - Node node = expression.getConditionalExpression(); - return FunctionCheckerDispatcher.getInstance() - .getFunctionChecker(node) - .checkFunction(node) ? VALID_FORMULA : INVALID_FORMULA; - } catch (ConditionCheckWrongException cce) { - String functionName = cce.getFunctionName(); - StringBuilder errorMsg = new StringBuilder(functionName + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Condition_Tips") + ":"); - return errorMsg.toString(); - } catch (FunctionCheckWrongException ce) { - List rules = ce.getRules(); - String functionName = ce.getFunctionName(); - StringBuilder errorMsg = new StringBuilder(functionName + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Error_Tips") + ":"); - for (int i = 0; i < rules.size(); i++) { - errorMsg.append("("); - if (rules.get(i).getParameterList().isEmpty()) { - errorMsg.append(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_No_Param")); - } - for (FunctionParameterType functionParameterType : rules.get(i).getParameterList()) { - errorMsg.append(getTypeString(functionParameterType)).append(","); - } - if (",".equals(errorMsg.charAt(errorMsg.length() - 1) + "")) { - errorMsg.deleteCharAt(errorMsg.length() - 1); - } - errorMsg.append(")"); - if (i != rules.size() - 1) { - errorMsg.append(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_Or")); - } - } - return errorMsg.toString(); - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - return INVALID_FORMULA; - // alex:继续往下面走,expression为null时告知不合法公式 - } - } - - private static String getTypeString(FunctionParameterType type) { - switch (type) { - case NUMBER: - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Number"); - case STRING: - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_String"); - case ANY: - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Any"); - case DATE: - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Date"); - case BOOLEAN: - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Boolean"); - case ARRAY: - return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Formula_Check_ParamType_Array"); - } - return ""; - } - private final ActionListener calculateActionListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String formulaText = formulaTextArea.getText().trim(); - String formulaValidMessage = getFormulaValidMessage(formulaText); + String formulaValidMessage = FormulaChecker.check(formulaText); + ; String unSupportFormula = containsUnsupportedSimulationFormulas(formulaText); if (unSupportFormula != null) { FineJOptionPane.showMessageDialog( From 694288b23d191bed1a7cbce113dd263b97df5dfe Mon Sep 17 00:00:00 2001 From: "Henry.Wang" Date: Tue, 28 Sep 2021 15:43:34 +0800 Subject: [PATCH 2/3] REPORT-59919 && REPORT-59921 && REPORT-59922 --- .../authority/FormulaAuthorityChecker.java | 66 +++++++++++++++++-- .../authority/JTemplateAuthorityChecker.java | 24 ++++--- 2 files changed, 74 insertions(+), 16 deletions(-) diff --git a/designer-base/src/main/java/com/fr/design/mainframe/authority/FormulaAuthorityChecker.java b/designer-base/src/main/java/com/fr/design/mainframe/authority/FormulaAuthorityChecker.java index d108c18d4..5121f03c4 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/authority/FormulaAuthorityChecker.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/authority/FormulaAuthorityChecker.java @@ -1,6 +1,7 @@ package com.fr.design.mainframe.authority; import com.fr.base.Formula; +import com.fr.stable.StringUtils; import org.jetbrains.annotations.Nullable; import java.util.Arrays; @@ -10,18 +11,71 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; public class FormulaAuthorityChecker extends ElementAuthorityChecker { - private static final Pattern FORMULA_PATTERN = Pattern.compile("^=SQL\\(\"(.+?)\","); + private static final Set CONNECTION_NAME_FORMULA_PATTERN = new HashSet<>(); + private static final Set DATASET_NAME_FORMULA_PATTERN = new HashSet<>(); + + static { + CONNECTION_NAME_FORMULA_PATTERN.add(new FormulaPattern("^=SQL\\(\"(.+?)\",", 1)); + DATASET_NAME_FORMULA_PATTERN.add(new FormulaPattern("^=VALUE\\(\"(.+?)\",", 1)); + } @Override @Nullable public Set getNoAuthConnectionNames(Formula formula, Set authConnectionNames) { - String content = formula.getContent(); - Matcher matcher = FORMULA_PATTERN.matcher(content); - if (matcher.find()) { - if (!authConnectionNames.contains(matcher.group(1))) { - return new HashSet<>(Arrays.asList(matcher.group(1))); + return getNoAuthNames(formula, CONNECTION_NAME_FORMULA_PATTERN, authConnectionNames); + } + + @Override + @Nullable + Set getNoAuthDatasetNames(Formula formula, Set authDatasetNames) { + return getNoAuthNames(formula, DATASET_NAME_FORMULA_PATTERN, authDatasetNames); + } + + private Set getNoAuthNames(Formula formula, Set formulaPatterns, Set authNames) { + Set noAuthNames = new HashSet<>(); + for (FormulaPattern formulaPattern : formulaPatterns) { + String noAuthName = getNoAuthName(formula, formulaPattern, authNames); + if (noAuthName != null) { + noAuthNames.add(noAuthName); } } + return noAuthNames; + } + + private String getNoAuthName(Formula formula, FormulaPattern formulaPattern, Set authNames) { + String parameter = getFormulaParameter(formula, formulaPattern); + if (!authNames.contains(parameter)) { + return parameter; + } return null; } + + private String getFormulaParameter(Formula formula, FormulaPattern formulaPattern) { + String content = transformFormulaContent(formula.getContent()); + Matcher matcher = formulaPattern.pattern.matcher(content); + if (matcher.find()) { + return matcher.group(formulaPattern.index); + } + return null; + } + + private String transformFormulaContent(String content) { + int index = content.indexOf('('); + if (index > 0) { + return content.substring(0, index).toUpperCase() + content.substring(index); + } else { + return StringUtils.EMPTY; + } + } + + static class FormulaPattern { + public Pattern pattern; + public int index; + + FormulaPattern(String regex, int index) { + this.pattern = Pattern.compile(regex); + this.index = index; + } + } + } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/authority/JTemplateAuthorityChecker.java b/designer-base/src/main/java/com/fr/design/mainframe/authority/JTemplateAuthorityChecker.java index f8b2c8ce6..d76031f65 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/authority/JTemplateAuthorityChecker.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/authority/JTemplateAuthorityChecker.java @@ -7,11 +7,11 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.JTemplate; import com.fr.design.mod.ModClassFilter; +import com.fr.file.ConnectionConfig; +import com.fr.file.TableDataConfig; import com.fr.invoke.ClassHelper; import com.fr.log.FineLoggerFactory; -import com.fr.rpc.ExceptionHandler; -import com.fr.rpc.RPCInvokerExceptionInfo; import com.fr.stable.Filter; import com.fr.workspace.WorkContext; import com.fr.workspace.server.authority.user.UserAuthority; @@ -19,7 +19,6 @@ import com.fr.workspace.server.authority.user.UserAuthority; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -29,7 +28,9 @@ import static javax.swing.JOptionPane.WARNING_MESSAGE; public class JTemplateAuthorityChecker { JTemplate jTemplate; + Set allConnectionNames; Set authConnectionNames; + Set allDatasetNames; Set authDatasetNames; Map checkerMap = new HashMap<>(); Set authFailConnectionNames = new HashSet<>(); @@ -45,18 +46,20 @@ public class JTemplateAuthorityChecker { } private void initAuthNames() { + allDatasetNames = new HashSet<>(); + for (String authServerDataSetName : TableDataConfig.getInstance().getTableDatas().keySet()) { + allDatasetNames.add(authServerDataSetName); + } + + allConnectionNames = ConnectionConfig.getInstance().getConnections().keySet(); + UserAuthority templateAuthority = WorkContext.getCurrent().get(UserAuthority.class); Map> authNamesMap = templateAuthority.getAuthServerDataSetAndConnectionNames(); if (authNamesMap != null) { //有权限的数据连接名称 authConnectionNames = authNamesMap.get(UserAuthority.AUTH_CONNECTION_NAMES); - //有权限的数据集名称(模板数据集和服务器数据集) + //有权限的数据集名称 authDatasetNames = authNamesMap.get(UserAuthority.AUTH_SERVER_DATASET_NAMES); - Iterator iterator = jTemplate.getTarget().getTableDataNameIterator(); - while (iterator.hasNext()) { - String datasetName = iterator.next(); - authDatasetNames.add(datasetName); - } } } @@ -95,7 +98,8 @@ public class JTemplateAuthorityChecker { } } } - + authFailConnectionNames.retainAll(allConnectionNames); + authFailDatasetNames.retainAll(allDatasetNames); FineLoggerFactory.getLogger().info("JTemplateAuthorityChecker check time consume:" + (System.currentTimeMillis() - s)); return authFailConnectionNames.size() == 0 && authFailDatasetNames.size() == 0; } From 162108f4f0c79f705d6e7fec8cd3ffacbd42b667 Mon Sep 17 00:00:00 2001 From: "Henry.Wang" Date: Tue, 28 Sep 2021 18:11:28 +0800 Subject: [PATCH 3/3] REPORT-59919 && REPORT-59921 && REPORT-59922 --- .../authority/FormulaAuthorityChecker.java | 98 +++++++++++-------- 1 file changed, 57 insertions(+), 41 deletions(-) diff --git a/designer-base/src/main/java/com/fr/design/mainframe/authority/FormulaAuthorityChecker.java b/designer-base/src/main/java/com/fr/design/mainframe/authority/FormulaAuthorityChecker.java index 5121f03c4..15a7f4853 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/authority/FormulaAuthorityChecker.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/authority/FormulaAuthorityChecker.java @@ -1,81 +1,97 @@ package com.fr.design.mainframe.authority; import com.fr.base.Formula; -import com.fr.stable.StringUtils; +import com.fr.general.ComparatorUtils; +import com.fr.parser.FunctionCall; +import com.fr.parser.StringLiteral; +import com.fr.script.Calculator; +import com.fr.stable.script.Node; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; import java.util.HashSet; import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; public class FormulaAuthorityChecker extends ElementAuthorityChecker { - private static final Set CONNECTION_NAME_FORMULA_PATTERN = new HashSet<>(); - private static final Set DATASET_NAME_FORMULA_PATTERN = new HashSet<>(); + private static final Set CONNECTION_NAME_FORMULA_PARSER = new HashSet<>(); + private static final Set DATASET_NAME_FORMULA_PARSER = new HashSet<>(); static { - CONNECTION_NAME_FORMULA_PATTERN.add(new FormulaPattern("^=SQL\\(\"(.+?)\",", 1)); - DATASET_NAME_FORMULA_PATTERN.add(new FormulaPattern("^=VALUE\\(\"(.+?)\",", 1)); + CONNECTION_NAME_FORMULA_PARSER.add(new FormulaParser("SQL", 0)); + DATASET_NAME_FORMULA_PARSER.add(new FormulaParser("VALUE", 0)); } @Override @Nullable public Set getNoAuthConnectionNames(Formula formula, Set authConnectionNames) { - return getNoAuthNames(formula, CONNECTION_NAME_FORMULA_PATTERN, authConnectionNames); + return getNoAuthNames(formula, CONNECTION_NAME_FORMULA_PARSER, authConnectionNames); } + @Override @Nullable Set getNoAuthDatasetNames(Formula formula, Set authDatasetNames) { - return getNoAuthNames(formula, DATASET_NAME_FORMULA_PATTERN, authDatasetNames); + return getNoAuthNames(formula, DATASET_NAME_FORMULA_PARSER, authDatasetNames); } - private Set getNoAuthNames(Formula formula, Set formulaPatterns, Set authNames) { + private Set getNoAuthNames(Formula formula, Set formulaParsers, Set authNames) { Set noAuthNames = new HashSet<>(); - for (FormulaPattern formulaPattern : formulaPatterns) { - String noAuthName = getNoAuthName(formula, formulaPattern, authNames); + try { + FunctionCall functionCall = (FunctionCall) Calculator.createCalculator().parse(formula.getContent()).getConditionalExpression(); + handleNoAuthNames(functionCall, formulaParsers, authNames, noAuthNames); + } catch (Exception ignore) { + + } finally { + return noAuthNames; + } + } + + private void handleNoAuthNames(FunctionCall functionCall, Set formulaParsers, Set authNames, Set noAuthNames) { + for (FormulaParser formulaPattern : formulaParsers) { + String noAuthName = formulaPattern.getNoAuthName(functionCall, authNames); if (noAuthName != null) { noAuthNames.add(noAuthName); } } - return noAuthNames; - } - - private String getNoAuthName(Formula formula, FormulaPattern formulaPattern, Set authNames) { - String parameter = getFormulaParameter(formula, formulaPattern); - if (!authNames.contains(parameter)) { - return parameter; + Node[] nodes = functionCall.getArguments(); + if (nodes != null) { + for (int i = 0; i < nodes.length; i++) { + Node node = nodes[i]; + if (node instanceof FunctionCall) { + handleNoAuthNames((FunctionCall) node, formulaParsers, authNames, noAuthNames); + } + } } - return null; - } - private String getFormulaParameter(Formula formula, FormulaPattern formulaPattern) { - String content = transformFormulaContent(formula.getContent()); - Matcher matcher = formulaPattern.pattern.matcher(content); - if (matcher.find()) { - return matcher.group(formulaPattern.index); - } - return null; } - private String transformFormulaContent(String content) { - int index = content.indexOf('('); - if (index > 0) { - return content.substring(0, index).toUpperCase() + content.substring(index); - } else { - return StringUtils.EMPTY; - } - } - static class FormulaPattern { - public Pattern pattern; + static class FormulaParser { + //函数的名称 + public String name; + //要检测的位置 public int index; - FormulaPattern(String regex, int index) { - this.pattern = Pattern.compile(regex); + + FormulaParser(String name, int index) { + this.name = name; this.index = index; } + + String getNoAuthName(FunctionCall functionCall, Set authNames) { + if (functionCall.getName() != null && ComparatorUtils.equals(functionCall.getName().toUpperCase(), name)) { + Node node = functionCall.getArguments()[index]; + if (node instanceof StringLiteral) { + String stringLiteral = node.toString(); + if (stringLiteral.length() > 2) { + String value = stringLiteral.substring(1, stringLiteral.length() - 1); + if (!authNames.contains(value)) { + return value; + } + } + } + } + return null; + } } }