Skip to content

Commit

Permalink
Fix the SonarCloud issue in EspressoInlineExpressionParser
Browse files Browse the repository at this point in the history
  • Loading branch information
linghengqian committed Oct 9, 2023
1 parent cf2ec23 commit 176eb69
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 90 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
+++
title = "行表达式"
weight = 8
weight = 10
+++

## 使用 Groovy 语法的行表达式
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
+++
title = "Row Value Expressions"
weight = 8
weight = 10
+++

## Row Value Expressions that uses the Groovy syntax
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.google.common.collect.Sets;
import groovy.lang.GroovyShell;
import org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser;
import org.apache.shardingsphere.infra.util.groovy.GroovyUtils;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;

Expand All @@ -42,8 +43,6 @@ public final class EspressoInlineExpressionParser implements InlineExpressionPar

private static final String JAVA_CLASSPATH;

private static final char SPLITTER = ',';

private String inlineExpression;

/**
Expand Down Expand Up @@ -85,48 +84,7 @@ private String handlePlaceHolder(final String inlineExpression) {

@Override
public List<String> splitAndEvaluate() {
return Strings.isNullOrEmpty(inlineExpression) ? Collections.emptyList() : flatten(evaluate(split(handlePlaceHolder(inlineExpression)), context));
}

private List<String> split(final String inlineExpression) {
List<String> result = new ArrayList<>();
StringBuilder segment = new StringBuilder();
int bracketsDepth = 0;
for (int i = 0; i < inlineExpression.length(); i++) {
char each = inlineExpression.charAt(i);
switch (each) {
case SPLITTER:
if (bracketsDepth > 0) {
segment.append(each);
} else {
result.add(segment.toString().trim());
segment.setLength(0);
}
break;
case '$':
if ('{' == inlineExpression.charAt(i + 1)) {
bracketsDepth++;
}
if ("->{".equals(inlineExpression.substring(i + 1, i + 4))) {
bracketsDepth++;
}
segment.append(each);
break;
case '}':
if (bracketsDepth > 0) {
bracketsDepth--;
}
segment.append(each);
break;
default:
segment.append(each);
break;
}
}
if (segment.length() > 0) {
result.add(segment.toString().trim());
}
return result;
return Strings.isNullOrEmpty(inlineExpression) ? Collections.emptyList() : flatten(evaluate(GroovyUtils.split(handlePlaceHolder(inlineExpression)), context));
}

private List<Value> evaluate(final List<String> inlineExpressions, final Context context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import org.apache.shardingsphere.infra.expr.spi.InlineExpressionParser;
import org.apache.shardingsphere.infra.util.groovy.GroovyUtils;

import java.util.ArrayList;
import java.util.Collection;
Expand All @@ -41,8 +42,6 @@
*/
public final class GroovyInlineExpressionParser implements InlineExpressionParser {

private static final char SPLITTER = ',';

private static final String INLINE_EXPRESSION_KEY = "inlineExpression";

private static final Map<String, Script> SCRIPTS = new ConcurrentHashMap<>();
Expand Down Expand Up @@ -78,7 +77,7 @@ private String handlePlaceHolder(final String inlineExpression) {
*/
@Override
public List<String> splitAndEvaluate() {
return Strings.isNullOrEmpty(inlineExpression) ? Collections.emptyList() : flatten(evaluate(split(handlePlaceHolder(inlineExpression))));
return Strings.isNullOrEmpty(inlineExpression) ? Collections.emptyList() : flatten(evaluate(GroovyUtils.split(handlePlaceHolder(inlineExpression))));
}

/**
Expand Down Expand Up @@ -117,47 +116,6 @@ private Object evaluate(final String expression) {
return script.run();
}

private List<String> split(final String inlineExpression) {
List<String> result = new ArrayList<>();
StringBuilder segment = new StringBuilder();
int bracketsDepth = 0;
for (int i = 0; i < inlineExpression.length(); i++) {
char each = inlineExpression.charAt(i);
switch (each) {
case SPLITTER:
if (bracketsDepth > 0) {
segment.append(each);
} else {
result.add(segment.toString().trim());
segment.setLength(0);
}
break;
case '$':
if ('{' == inlineExpression.charAt(i + 1)) {
bracketsDepth++;
}
if ("->{".equals(inlineExpression.substring(i + 1, i + 4))) {
bracketsDepth++;
}
segment.append(each);
break;
case '}':
if (bracketsDepth > 0) {
bracketsDepth--;
}
segment.append(each);
break;
default:
segment.append(each);
break;
}
}
if (segment.length() > 0) {
result.add(segment.toString().trim());
}
return result;
}

private List<String> flatten(final List<Object> segments) {
List<String> result = new ArrayList<>();
for (Object each : segments) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.shardingsphere.infra.util.groovy;

import java.util.ArrayList;
import java.util.List;

/**
* GroovyShell expression common utils. It mainly serves the use of the following classes.
* - `org.apache.shardingsphere.infra.expr.espresso.EspressoInlineExpressionParser`
* - `org.apache.shardingsphere.infra.expr.groovy.GroovyInlineExpressionParser`
*/
public class GroovyUtils {

/**
* Split GroovyShell expression to a ArrayList.
*
* @return result ArrayList of GroovyShell expression with {@code $}.
*/
public static List<String> split(final String inlineExpression) {
List<String> result = new ArrayList<>();
StringBuilder segment = new StringBuilder();
int bracketsDepth = 0;
for (int i = 0; i < inlineExpression.length(); i++) {
char each = inlineExpression.charAt(i);
switch (each) {
case ',':
handleSplitter(bracketsDepth, segment, each, result);
break;
case '$':
bracketsDepth = handleDollarSign(inlineExpression, i, bracketsDepth, segment, each);
break;
case '}':
bracketsDepth = handleClosingBracket(bracketsDepth, segment, each);
break;
default:
segment.append(each);
break;
}
}
if (segment.length() > 0) {
result.add(segment.toString().trim());
}
return result;
}

private static void handleSplitter(final int bracketsDepth, final StringBuilder segment, final char each, final List<String> result) {
if (bracketsDepth > 0) {
segment.append(each);
} else {
result.add(segment.toString().trim());
segment.setLength(0);
}
}

private static int handleDollarSign(final String inlineExpression, final int i, final int bracketsDepth, final StringBuilder segment, final char each) {
int bracketsDepthResult = bracketsDepth;
if ('{' == inlineExpression.charAt(i + 1)) {
bracketsDepthResult = bracketsDepthResult + 1;
}
if ("->{".equals(inlineExpression.substring(i + 1, i + 4))) {
bracketsDepthResult = bracketsDepthResult + 1;
}
segment.append(each);
return bracketsDepthResult;
}

private static int handleClosingBracket(final int bracketsDepth, final StringBuilder segment, final char each) {
segment.append(each);
return bracketsDepth > 0 ? bracketsDepth - 1 : bracketsDepth;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.shardingsphere.infra.util.groovy;

import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.Collections;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

class GroovyUtilsTest {

@Test
void assertSplit() {
assertThat(GroovyUtils.split(" t_order_0, t_order_1 "), is(Arrays.asList("t_order_0", "t_order_1")));
assertThat(GroovyUtils.split("t_order_${null}"), is(Collections.singletonList("t_order_${null}")));
assertThat(GroovyUtils.split("t_order_${'xx'}"), is(Collections.singletonList("t_order_${'xx'}")));
assertThat(GroovyUtils.split("t_order_${[0, 1, 2]},t_order_item_${[0, 2]}"),
is(Arrays.asList("t_order_${[0, 1, 2]}", "t_order_item_${[0, 2]}")));
assertThat(GroovyUtils.split("t_order_${0..2},t_order_item_${0..1}"), is(Arrays.asList("t_order_${0..2}", "t_order_item_${0..1}")));
assertThat(GroovyUtils.split("t_${[\"new${1+2}\",'old']}_order_${1..2}"),
is(Collections.singletonList("t_${[\"new${1+2}\",'old']}_order_${1..2}")));
assertThat(GroovyUtils.split("t_$->{[\"new$->{1+2}\",'old']}_order_$->{1..2}"),
is(Collections.singletonList("t_$->{[\"new$->{1+2}\",'old']}_order_$->{1..2}")));
}
}

0 comments on commit 176eb69

Please sign in to comment.