All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.shardingsphere.core.util.InlineExpressionParser Maven / Gradle / Ivy

There is a newer version: 3.1.0
Show newest version
/*
 * 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 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; /** * Inline expression parser. * * @author gaohongtao * @author zhangliang */ @RequiredArgsConstructor 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 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; } /** * Split and evaluate inline expression. * * @return result list */ 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) { StringBuilder expression = new StringBuilder(handlePlaceHolder(each)); if (!each.startsWith("\"")) { expression.insert(0, "\""); } if (!each.endsWith("\"")) { expression.append("\""); } 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(); 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 flatten(final List segments) { List result = new ArrayList<>(); for (Object each : segments) { if (each instanceof GString) { result.addAll(assemblyCartesianSegments((GString) each)); } else { result.add(each.toString()); } } return result; } private List assemblyCartesianSegments(final GString segment) { Set> cartesianValues = getCartesianValues(segment); List result = new ArrayList<>(cartesianValues.size()); for (List each : cartesianValues) { result.add(assemblySegment(each, segment)); } return result; } @SuppressWarnings("unchecked") private Set> getCartesianValues(final GString segment) { List> result = new ArrayList<>(segment.getValues().length); for (Object each : segment.getValues()) { if (null == each) { continue; } if (each instanceof Collection) { result.add(Sets.newLinkedHashSet(Collections2.transform((Collection) each, new Function() { @Override public String apply(final Object input) { return input.toString(); } }))); } else { result.add(Sets.newHashSet(each.toString())); } } return Sets.cartesianProduct(result); } private String assemblySegment(final List cartesianValue, final GString segment) { StringBuilder result = new StringBuilder(); for (int i = 0; i < segment.getStrings().length; i++) { result.append(segment.getStrings()[i]); if (i < cartesianValue.size()) { result.append(cartesianValue.get(i)); } } return result.toString(); } }