From c75a67f75bf4f2a1745743ef57afbba5ce1a131b Mon Sep 17 00:00:00 2001 From: terrymanu Date: Sat, 9 Jun 2018 00:23:33 +0800 Subject: [PATCH] for #920, encapsulate closure to InlineExpressionParser --- .../inline/InlineShardingStrategy.java | 4 +- .../shardingsphere/core/rule/TableRule.java | 2 +- .../shardingsphere/core/util/GroovyUtil.java | 56 ------------------- .../core/util/InlineExpressionParser.java | 41 ++++++++++++-- .../core/util/InlineExpressionParserTest.java | 20 +++---- .../cases/dataset/init/DataSetsRoot.java | 2 +- .../dbtest/engine/DMLIntegrateTest.java | 2 +- .../dataset/DataSetEnvironmentManager.java | 2 +- 8 files changed, 51 insertions(+), 78 deletions(-) delete mode 100644 sharding-core/src/main/java/io/shardingsphere/core/util/GroovyUtil.java diff --git a/sharding-core/src/main/java/io/shardingsphere/core/routing/strategy/inline/InlineShardingStrategy.java b/sharding-core/src/main/java/io/shardingsphere/core/routing/strategy/inline/InlineShardingStrategy.java index 51479181125c0..bde9c9e1f985a 100644 --- a/sharding-core/src/main/java/io/shardingsphere/core/routing/strategy/inline/InlineShardingStrategy.java +++ b/sharding-core/src/main/java/io/shardingsphere/core/routing/strategy/inline/InlineShardingStrategy.java @@ -17,7 +17,6 @@ package io.shardingsphere.core.routing.strategy.inline; -import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import groovy.lang.Closure; import groovy.util.Expando; @@ -26,7 +25,6 @@ import io.shardingsphere.core.api.algorithm.sharding.ShardingValue; import io.shardingsphere.core.api.config.strategy.InlineShardingStrategyConfiguration; import io.shardingsphere.core.routing.strategy.ShardingStrategy; -import io.shardingsphere.core.util.GroovyUtil; import io.shardingsphere.core.util.InlineExpressionParser; import java.util.ArrayList; @@ -51,7 +49,7 @@ public InlineShardingStrategy(final InlineShardingStrategyConfiguration inlineSh Preconditions.checkNotNull(inlineShardingStrategyConfig.getAlgorithmExpression(), "Sharding algorithm expression cannot be null."); shardingColumn = inlineShardingStrategyConfig.getShardingColumn(); String algorithmExpression = InlineExpressionParser.handlePlaceHolder(inlineShardingStrategyConfig.getAlgorithmExpression().trim()); - closure = (Closure) GroovyUtil.evaluate(Joiner.on("").join("{it -> \"", algorithmExpression, "\"}")); + closure = new InlineExpressionParser(algorithmExpression).evaluateClosure(); } @Override diff --git a/sharding-core/src/main/java/io/shardingsphere/core/rule/TableRule.java b/sharding-core/src/main/java/io/shardingsphere/core/rule/TableRule.java index 225d51e9fada4..9e5eb49ccd60f 100644 --- a/sharding-core/src/main/java/io/shardingsphere/core/rule/TableRule.java +++ b/sharding-core/src/main/java/io/shardingsphere/core/rule/TableRule.java @@ -58,7 +58,7 @@ public final class TableRule { public TableRule(final TableRuleConfiguration tableRuleConfig, final ShardingDataSourceNames shardingDataSourceNames) { Preconditions.checkNotNull(tableRuleConfig.getLogicTable(), "Logic table cannot be null."); logicTable = tableRuleConfig.getLogicTable().toLowerCase(); - List dataNodes = new InlineExpressionParser(tableRuleConfig.getActualDataNodes()).evaluate(); + List dataNodes = new InlineExpressionParser(tableRuleConfig.getActualDataNodes()).splitAndEvaluate(); actualDataNodes = isEmptyDataNodes(dataNodes) ? generateDataNodes(tableRuleConfig.getLogicTable(), shardingDataSourceNames.getDataSourceNames()) : generateDataNodes(dataNodes, shardingDataSourceNames.getDataSourceNames()); databaseShardingStrategy = null == tableRuleConfig.getDatabaseShardingStrategyConfig() ? null : ShardingStrategyFactory.newInstance(tableRuleConfig.getDatabaseShardingStrategyConfig()); diff --git a/sharding-core/src/main/java/io/shardingsphere/core/util/GroovyUtil.java b/sharding-core/src/main/java/io/shardingsphere/core/util/GroovyUtil.java deleted file mode 100644 index 80b8c0d631382..0000000000000 --- a/sharding-core/src/main/java/io/shardingsphere/core/util/GroovyUtil.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2016-2018 shardingsphere.io. - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *

- */ - -package io.shardingsphere.core.util; - -import groovy.lang.GroovyShell; -import groovy.lang.Script; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Groovy util. - * - * @author Pramy - */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public final class GroovyUtil { - - private static final Map SCRIPTS = new ConcurrentHashMap<>(); - - private static final GroovyShell SHELL = new GroovyShell(); - - /** - * evaluate expression. - * - * @param expression expression - * @return result of expression execution - */ - public static Object evaluate(final String expression) { - Script script; - if (SCRIPTS.containsKey(expression)) { - script = SCRIPTS.get(expression); - } else { - script = SHELL.parse(expression); - SCRIPTS.put(expression, script); - } - return script.run(); - } -} diff --git a/sharding-core/src/main/java/io/shardingsphere/core/util/InlineExpressionParser.java b/sharding-core/src/main/java/io/shardingsphere/core/util/InlineExpressionParser.java index 90c2ff7b29516..d09f9d492bc4b 100644 --- a/sharding-core/src/main/java/io/shardingsphere/core/util/InlineExpressionParser.java +++ b/sharding-core/src/main/java/io/shardingsphere/core/util/InlineExpressionParser.java @@ -18,15 +18,21 @@ package io.shardingsphere.core.util; import com.google.common.base.Function; +import com.google.common.base.Joiner; import com.google.common.collect.Collections2; import com.google.common.collect.Sets; +import groovy.lang.Closure; import groovy.lang.GString; +import groovy.lang.GroovyShell; +import groovy.lang.Script; import lombok.RequiredArgsConstructor; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; /** @@ -40,12 +46,17 @@ public final class InlineExpressionParser { private static final char SPLITTER = ','; + private static final Map SCRIPTS = new HashMap<>(); + + private static final GroovyShell SHELL = new GroovyShell(); + private final String inlineExpression; /** - * Replace all the inlineExpression placeholders. - * @param inlineExpression inlineExpression - * @return result inlineExpression + * Replace all inline expression placeholders. + * + * @param inlineExpression inline expression with {@code $->} + * @return result inline expression with {@code $} */ public static String handlePlaceHolder(final String inlineExpression) { return inlineExpression.contains("$->{") ? inlineExpression.replaceAll("\\$->\\{", "\\$\\{") : inlineExpression; @@ -56,13 +67,22 @@ public static String handlePlaceHolder(final String inlineExpression) { * * @return result list */ - public List evaluate() { + public List splitAndEvaluate() { if (null == inlineExpression) { return Collections.emptyList(); } return flatten(evaluate(split())); } + /** + * Evaluate closure. + * + * @return closure + */ + public Closure evaluateClosure() { + return (Closure) evaluate(Joiner.on("").join("{it -> \"", inlineExpression, "\"}")); + } + private List evaluate(final List inlineExpressions) { List result = new ArrayList<>(inlineExpressions.size()); for (String each : inlineExpressions) { @@ -73,11 +93,22 @@ private List evaluate(final List inlineExpressions) { if (!each.endsWith("\"")) { expression.append("\""); } - result.add(GroovyUtil.evaluate(expression.toString())); + result.add(evaluate(expression.toString())); } return result; } + private Object evaluate(final String expression) { + Script script; + if (SCRIPTS.containsKey(expression)) { + script = SCRIPTS.get(expression); + } else { + script = SHELL.parse(expression); + SCRIPTS.put(expression, script); + } + return script.run(); + } + private List split() { List result = new ArrayList<>(); StringBuilder segment = new StringBuilder(); diff --git a/sharding-core/src/test/java/io/shardingsphere/core/util/InlineExpressionParserTest.java b/sharding-core/src/test/java/io/shardingsphere/core/util/InlineExpressionParserTest.java index 838ae2fc5fe33..1974d17497984 100644 --- a/sharding-core/src/test/java/io/shardingsphere/core/util/InlineExpressionParserTest.java +++ b/sharding-core/src/test/java/io/shardingsphere/core/util/InlineExpressionParserTest.java @@ -30,62 +30,62 @@ public final class InlineExpressionParserTest { @Test public void assertEvaluateForExpressionIsNull() { - List expected = new InlineExpressionParser(null).evaluate(); + List expected = new InlineExpressionParser(null).splitAndEvaluate(); assertThat(expected, is(Collections.emptyList())); } @Test public void assertEvaluateForSimpleString() { - List expected = new InlineExpressionParser(" t_order_0, t_order_1 ").evaluate(); + List expected = new InlineExpressionParser(" t_order_0, t_order_1 ").splitAndEvaluate(); assertThat(expected.size(), is(2)); assertThat(expected, hasItems("t_order_0", "t_order_1")); } @Test public void assertEvaluateForNull() { - List expected = new InlineExpressionParser("t_order_${null}").evaluate(); + List expected = new InlineExpressionParser("t_order_${null}").splitAndEvaluate(); assertThat(expected.size(), is(1)); assertThat(expected, hasItems("t_order_")); } @Test public void assertEvaluateForLiteral() { - List expected = new InlineExpressionParser("t_order_${'xx'}").evaluate(); + List expected = new InlineExpressionParser("t_order_${'xx'}").splitAndEvaluate(); assertThat(expected.size(), is(1)); assertThat(expected, hasItems("t_order_xx")); } @Test public void assertEvaluateForArray() { - List expected = new InlineExpressionParser("t_order_${[0, 1, 2]},t_order_item_${[0, 2]}").evaluate(); + List expected = new InlineExpressionParser("t_order_${[0, 1, 2]},t_order_item_${[0, 2]}").splitAndEvaluate(); assertThat(expected.size(), is(5)); assertThat(expected, hasItems("t_order_0", "t_order_1", "t_order_2", "t_order_item_0", "t_order_item_2")); } @Test public void assertEvaluateForRange() { - List expected = new InlineExpressionParser("t_order_${0..2},t_order_item_${0..1}").evaluate(); + List expected = new InlineExpressionParser("t_order_${0..2},t_order_item_${0..1}").splitAndEvaluate(); assertThat(expected.size(), is(5)); assertThat(expected, hasItems("t_order_0", "t_order_1", "t_order_2", "t_order_item_0", "t_order_item_1")); } @Test public void assertEvaluateForComplex() { - List expected = new InlineExpressionParser("t_${['new','old']}_order_${1..2}, t_config").evaluate(); + List expected = new InlineExpressionParser("t_${['new','old']}_order_${1..2}, t_config").splitAndEvaluate(); assertThat(expected.size(), is(5)); assertThat(expected, hasItems("t_new_order_1", "t_new_order_2", "t_old_order_1", "t_old_order_2", "t_config")); } @Test public void assertEvaluateForCalculate() { - List expected = new InlineExpressionParser("t_${[\"new${1+2}\",'old']}_order_${1..2}").evaluate(); + List expected = new InlineExpressionParser("t_${[\"new${1+2}\",'old']}_order_${1..2}").splitAndEvaluate(); assertThat(expected.size(), is(4)); assertThat(expected, hasItems("t_new3_order_1", "t_new3_order_2", "t_old_order_1", "t_old_order_2")); } @Test public void assertEvaluateForExpressionPlaceHolder() { - List expected = new InlineExpressionParser("t_$->{[\"new$->{1+2}\",'old']}_order_$->{1..2}").evaluate(); + List expected = new InlineExpressionParser("t_$->{[\"new$->{1+2}\",'old']}_order_$->{1..2}").splitAndEvaluate(); assertThat(expected.size(), is(4)); assertThat(expected, hasItems("t_new3_order_1", "t_new3_order_2", "t_old_order_1", "t_old_order_2")); } @@ -102,7 +102,7 @@ public void assertEvaluateForLong() { expression.append(","); } } - List expected = new InlineExpressionParser(expression.toString()).evaluate(); + List expected = new InlineExpressionParser(expression.toString()).splitAndEvaluate(); assertThat(expected.size(), is(1024)); assertThat(expected, hasItems("ds_0.t_user_0", "ds_15.t_user_1023")); } diff --git a/sharding-jdbc/src/test/java/io/shardingsphere/dbtest/cases/dataset/init/DataSetsRoot.java b/sharding-jdbc/src/test/java/io/shardingsphere/dbtest/cases/dataset/init/DataSetsRoot.java index 0c55608e7dc82..c7c0b70968f95 100644 --- a/sharding-jdbc/src/test/java/io/shardingsphere/dbtest/cases/dataset/init/DataSetsRoot.java +++ b/sharding-jdbc/src/test/java/io/shardingsphere/dbtest/cases/dataset/init/DataSetsRoot.java @@ -44,7 +44,7 @@ public final class DataSetsRoot { */ public DataSetMetadata findDataSetMetadata(final DataNode dataNode) { for (DataSetMetadata each : metadataList) { - if (contains(new InlineExpressionParser(each.getDataNodes()).evaluate(), dataNode)) { + if (contains(new InlineExpressionParser(each.getDataNodes()).splitAndEvaluate(), dataNode)) { return each; } } diff --git a/sharding-jdbc/src/test/java/io/shardingsphere/dbtest/engine/DMLIntegrateTest.java b/sharding-jdbc/src/test/java/io/shardingsphere/dbtest/engine/DMLIntegrateTest.java index cbc7c19f87a29..77b6e5d9562f8 100644 --- a/sharding-jdbc/src/test/java/io/shardingsphere/dbtest/engine/DMLIntegrateTest.java +++ b/sharding-jdbc/src/test/java/io/shardingsphere/dbtest/engine/DMLIntegrateTest.java @@ -182,7 +182,7 @@ private void assertDataSet() throws SQLException, IOException, JAXBException { } assertThat("Only support single table for DML.", expected.getMetadataList().size(), is(1)); DataSetMetadata expectedDataSetMetadata = expected.getMetadataList().get(0); - for (String each : new InlineExpressionParser(expectedDataSetMetadata.getDataNodes()).evaluate()) { + for (String each : new InlineExpressionParser(expectedDataSetMetadata.getDataNodes()).splitAndEvaluate()) { DataNode dataNode = new DataNode(each); try (Connection connection = getDataSourceMap().get(dataNode.getDataSourceName()).getConnection(); PreparedStatement preparedStatement = connection.prepareStatement(String.format("SELECT * FROM %s", dataNode.getTableName()))) { diff --git a/sharding-jdbc/src/test/java/io/shardingsphere/dbtest/env/dataset/DataSetEnvironmentManager.java b/sharding-jdbc/src/test/java/io/shardingsphere/dbtest/env/dataset/DataSetEnvironmentManager.java index 33af4d150a7a0..bac114dde9e72 100644 --- a/sharding-jdbc/src/test/java/io/shardingsphere/dbtest/env/dataset/DataSetEnvironmentManager.java +++ b/sharding-jdbc/src/test/java/io/shardingsphere/dbtest/env/dataset/DataSetEnvironmentManager.java @@ -159,7 +159,7 @@ private Map> getDataNodeMap() { private Map> getDataNodeMap(final DataSetMetadata dataSetMetadata) { Map> result = new LinkedHashMap<>(); - for (String each : new InlineExpressionParser(dataSetMetadata.getDataNodes()).evaluate()) { + for (String each : new InlineExpressionParser(dataSetMetadata.getDataNodes()).splitAndEvaluate()) { DataNode dataNode = new DataNode(each); if (!result.containsKey(dataNode.getDataSourceName())) { result.put(dataNode.getDataSourceName(), new LinkedList());