/* * 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 com.facebook.presto.tests; import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.function.Consumer; import java.util.stream.IntStream; import java.util.stream.Stream; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.ImmutableList.toImmutableList; import static java.util.Objects.requireNonNull; public class QueryTemplate { public static QueryTemplate queryTemplate(String queryTemplate, Parameter... parameters) { return new QueryTemplate(queryTemplate, parameters); } public static Parameter parameter(String key) { return new Parameter(key); } private final String queryTemplate; private final List<Parameter> defaultParameters; private QueryTemplate(String queryTemplate, Parameter... parameters) { for (Parameter parameter : parameters) { String queryParameterKey = asQueryParameterKey(parameter.getKey()); checkArgument( queryTemplate.contains(queryParameterKey), "Query template does not contain: %s", queryParameterKey); } this.queryTemplate = queryTemplate; this.defaultParameters = ImmutableList.copyOf(parameters); } public String replace(Parameter... parameters) { String query = queryTemplate; for (Parameter parameter : parameters) { query = resolve(query, parameter); } for (Parameter parameter : defaultParameters) { query = resolve(query, parameter); } checkQueryHasAllParametersReplaced(query); return query; } private void checkQueryHasAllParametersReplaced(String query) { for (Parameter parameter : defaultParameters) { String queryParameterKey = asQueryParameterKey(parameter.getKey()); checkArgument( !query.contains(queryParameterKey), "Query template parameters was not given: %s", queryParameterKey); } } @SafeVarargs public final Stream<String> replaceAll(List<Parameter>... parametersLists) { List<String> queries = new ArrayList<>(); replaceAll(queries::add, parametersLists); return queries.stream(); } public void replaceAll(Consumer<String> queryConsumer, List<Parameter>... parametersLists) { requireNonNull(queryConsumer, "queryConsumer is null"); replaceAll(queryTemplate, queryConsumer, ImmutableList.copyOf(parametersLists)); } private void replaceAll(String queryTemplate, Consumer<String> queryConsumer, List<List<Parameter>> parametersLists) { if (parametersLists.size() == 0) { checkQueryHasAllParametersReplaced(queryTemplate); queryConsumer.accept(queryTemplate); } else { List<List<Parameter>> restParameters = IntStream.range(1, parametersLists.size()) .mapToObj(parametersLists::get) .collect(toImmutableList()); for (Parameter parameter : parametersLists.get(0)) { String intermediateQueryTemplate = resolve(queryTemplate, parameter); replaceAll(intermediateQueryTemplate, queryConsumer, restParameters); } } } private String resolve(String query, Parameter parameter) { return parameter.getValue() .map(value -> query.replaceAll(asQueryParameterKey(parameter.getKey()), value)) .orElse(query); } private String asQueryParameterKey(String key) { return "%" + key + "%"; } public static final class Parameter { private final String key; private final Optional<String> value; private Parameter(String key) { this(key, Optional.empty()); } private Parameter(String key, String value) { this(key, Optional.of(value)); } private Parameter(String key, Optional<String> value) { this.key = requireNonNull(key, "key is null"); this.value = requireNonNull(value, "defaultValue is null"); } public Optional<String> getValue() { return value; } public String getKey() { return key; } public Parameter of(String value) { return new Parameter(key, value); } public List<Parameter> of(String... values) { return Arrays.stream(values) .map(this::of) .collect(toImmutableList()); } } }