DATAES-552 - Polishing.

Update lookup to replace all matches & add some tests.

Original Pull Request: #267
This commit is contained in:
Christoph Strobl 2019-04-10 10:17:42 +02:00
parent cc8f0c8ab7
commit 3be6fad1fc
2 changed files with 110 additions and 5 deletions

View File

@ -19,12 +19,12 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.convert.DateTimeConverters;
import org.springframework.data.elasticsearch.core.query.StringQuery;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.util.Assert;
import org.springframework.util.NumberUtils;
/**
* ElasticsearchStringQuery
@ -83,13 +83,14 @@ public class ElasticsearchStringQuery extends AbstractElasticsearchRepositoryQue
}
private String replacePlaceholders(String input, ParametersParameterAccessor accessor) {
Matcher matcher = PARAMETER_PLACEHOLDER.matcher(input);
String result = input;
while (matcher.find()) {
String group = matcher.group();
group = "\\" + group;
int index = Integer.parseInt(matcher.group(1));
result = result.replaceFirst(group, getParameterWithIndex(accessor, index));
String placeholder = Pattern.quote(matcher.group()) + "(?!\\d+)";
int index = NumberUtils.parseNumber(matcher.group(1), Integer.class);
result = result.replaceAll(placeholder, getParameterWithIndex(accessor, index));
}
return result;
}

View File

@ -0,0 +1,104 @@
/*
* Copyright 2019 the original author or authors.
*
* 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
*
* https://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.springframework.data.elasticsearch.repository.query;
import static org.assertj.core.api.Assertions.*;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.data.elasticsearch.annotations.Query;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.elasticsearch.core.query.StringQuery;
import org.springframework.data.elasticsearch.entities.Person;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
import org.springframework.data.repository.query.ParametersParameterAccessor;
/**
* @author Christoph Strobl
*/
@RunWith(MockitoJUnitRunner.class)
public class ElasticsearchStringQueryUnitTests {
@Mock ElasticsearchOperations operations;
ElasticsearchConverter converter;
@Before
public void setUp() {
converter = new MappingElasticsearchConverter(new SimpleElasticsearchMappingContext());
}
@Test // DATAES-552
public void shouldReplaceParametersCorrectly() throws Exception {
org.springframework.data.elasticsearch.core.query.Query query = createQuery("findByName", "Luke");
assertThat(query).isInstanceOf(StringQuery.class);
assertThat(((StringQuery) query).getSource())
.isEqualTo("{ 'bool' : { 'must' : { 'term' : { 'name' : 'Luke' } } } }");
}
@Test // DATAES-552
public void shouldReplaceRepeatedParametersCorrectly() throws Exception {
org.springframework.data.elasticsearch.core.query.Query query = createQuery("findWithRepeatedPlaceholder", "zero",
"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven");
assertThat(query).isInstanceOf(StringQuery.class);
assertThat(((StringQuery) query).getSource())
.isEqualTo("name:(zero, eleven, one, two, three, four, five, six, seven, eight, nine, ten, eleven, zero, one)");
}
private org.springframework.data.elasticsearch.core.query.Query createQuery(String methodName, String... args)
throws NoSuchMethodException {
Class<?>[] argTypes = Arrays.stream(args).map(Object::getClass).toArray(size -> new Class[size]);
ElasticsearchQueryMethod queryMethod = getQueryMethod(methodName, argTypes);
ElasticsearchStringQuery elasticsearchStringQuery = queryForMethod(queryMethod);
return elasticsearchStringQuery.createQuery(new ParametersParameterAccessor(queryMethod.getParameters(), args));
}
private ElasticsearchStringQuery queryForMethod(ElasticsearchQueryMethod queryMethod) {
return new ElasticsearchStringQuery(queryMethod, operations, queryMethod.getAnnotatedQuery());
}
private ElasticsearchQueryMethod getQueryMethod(String name, Class<?>... parameters) throws NoSuchMethodException {
Method method = SampleRepository.class.getMethod(name, parameters);
return new ElasticsearchQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
new SpelAwareProxyProjectionFactory());
}
private interface SampleRepository extends Repository<Person, String> {
@Query("{ 'bool' : { 'must' : { 'term' : { 'name' : '?0' } } } }")
Person findByName(String name);
@Query(value = "name:(?0, ?11, ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?0, ?1)")
Person findWithRepeatedPlaceholder(String arg0, String arg1, String arg2, String arg3, String arg4, String arg5,
String arg6, String arg7, String arg8, String arg9, String arg10, String arg11);
}
}