Use pattern matching instead of type casting.

Original Pull Request #2784
Closes #2785
This commit is contained in:
Junghoon Ban 2023-12-03 21:22:06 +09:00 committed by GitHub
parent 415d5e0385
commit 8613eb26e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 59 additions and 49 deletions

View File

@ -50,6 +50,7 @@ import org.springframework.util.Assert;
* filter. * filter.
* *
* @author Peter-Josef Meisch * @author Peter-Josef Meisch
* @author Junghoon Ban
* @since 4.4 * @since 4.4
*/ */
class CriteriaFilterProcessor { class CriteriaFilterProcessor {
@ -169,7 +170,7 @@ class CriteriaFilterProcessor {
Assert.isTrue(values[1] instanceof String || values[1] instanceof Distance, Assert.isTrue(values[1] instanceof String || values[1] instanceof Distance,
"Second element of a geo distance filter must be a text or a Distance"); "Second element of a geo distance filter must be a text or a Distance");
String dist = (values[1] instanceof Distance) ? extractDistanceString((Distance) values[1]) : (String) values[1]; String dist = (values[1] instanceof Distance distance) ? extractDistanceString(distance) : (String) values[1];
return QueryBuilders.geoDistance() // return QueryBuilders.geoDistance() //
.field(fieldName) // .field(fieldName) //
@ -178,8 +179,8 @@ class CriteriaFilterProcessor {
.location(location -> { .location(location -> {
if (values[0]instanceof GeoPoint loc) { if (values[0]instanceof GeoPoint loc) {
location.latlon(latlon -> latlon.lat(loc.getLat()).lon(loc.getLon())); location.latlon(latlon -> latlon.lat(loc.getLat()).lon(loc.getLon()));
} else if (values[0] instanceof Point) { } else if (values[0] instanceof Point point) {
GeoPoint loc = GeoPoint.fromPoint((Point) values[0]); GeoPoint loc = GeoPoint.fromPoint(point);
location.latlon(latlon -> latlon.lat(loc.getLat()).lon(loc.getLon())); location.latlon(latlon -> latlon.lat(loc.getLat()).lon(loc.getLon()));
} else { } else {
String loc = (String) values[0]; String loc = (String) values[0];
@ -220,8 +221,8 @@ class CriteriaFilterProcessor {
"single-element of boundedBy filter must be type of GeoBox or Box"); "single-element of boundedBy filter must be type of GeoBox or Box");
GeoBox geoBBox; GeoBox geoBBox;
if (value instanceof Box) { if (value instanceof Box box) {
geoBBox = GeoBox.fromBox((Box) value); geoBBox = GeoBox.fromBox(box);
} else { } else {
geoBBox = (GeoBox) value; geoBBox = (GeoBox) value;
} }

View File

@ -40,6 +40,7 @@ import org.springframework.data.elasticsearch.VersionConflictException;
* appropriate: any other exception may have resulted from user code, and should not be translated. * appropriate: any other exception may have resulted from user code, and should not be translated.
* *
* @author Peter-Josef Meisch * @author Peter-Josef Meisch
* @author Junghoon Ban
* @since 4.4 * @since 4.4
*/ */
public class ElasticsearchExceptionTranslator implements PersistenceExceptionTranslator { public class ElasticsearchExceptionTranslator implements PersistenceExceptionTranslator {
@ -59,7 +60,7 @@ public class ElasticsearchExceptionTranslator implements PersistenceExceptionTra
*/ */
public RuntimeException translateException(Throwable throwable) { public RuntimeException translateException(Throwable throwable) {
RuntimeException runtimeException = throwable instanceof RuntimeException ? (RuntimeException) throwable RuntimeException runtimeException = throwable instanceof RuntimeException ex ? ex
: new RuntimeException(throwable.getMessage(), throwable); : new RuntimeException(throwable.getMessage(), throwable);
RuntimeException potentiallyTranslatedException = translateExceptionIfPossible(runtimeException); RuntimeException potentiallyTranslatedException = translateExceptionIfPossible(runtimeException);

View File

@ -79,6 +79,7 @@ import org.springframework.util.StringUtils;
* *
* @author Peter-Josef Meisch * @author Peter-Josef Meisch
* @author Illia Ulianov * @author Illia Ulianov
* @author Junghoon Ban
* @since 4.4 * @since 4.4
*/ */
public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearchTemplate { public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearchTemplate {
@ -645,7 +646,7 @@ public class ReactiveElasticsearchTemplate extends AbstractReactiveElasticsearch
*/ */
private RuntimeException translateException(Throwable throwable) { private RuntimeException translateException(Throwable throwable) {
RuntimeException runtimeException = throwable instanceof RuntimeException ? (RuntimeException) throwable RuntimeException runtimeException = throwable instanceof RuntimeException ex ? ex
: new RuntimeException(throwable.getMessage(), throwable); : new RuntimeException(throwable.getMessage(), throwable);
RuntimeException potentiallyTranslatedException = exceptionTranslator RuntimeException potentiallyTranslatedException = exceptionTranslator
.translateExceptionIfPossible(runtimeException); .translateExceptionIfPossible(runtimeException);

View File

@ -80,6 +80,7 @@ import org.springframework.util.ObjectUtils;
* @author Marc Vanbrabant * @author Marc Vanbrabant
* @author Anton Naydenov * @author Anton Naydenov
* @author vdisk * @author vdisk
* @author Junghoon Ban
* @since 3.2 * @since 3.2
*/ */
public class MappingElasticsearchConverter public class MappingElasticsearchConverter
@ -503,16 +504,16 @@ public class MappingElasticsearchConverter
private Object propertyConverterRead(ElasticsearchPersistentProperty property, Object source) { private Object propertyConverterRead(ElasticsearchPersistentProperty property, Object source) {
PropertyValueConverter propertyValueConverter = Objects.requireNonNull(property.getPropertyValueConverter()); PropertyValueConverter propertyValueConverter = Objects.requireNonNull(property.getPropertyValueConverter());
if (source instanceof String[]) { if (source instanceof String[] strings) {
// convert to a List // convert to a List
source = Arrays.asList((String[]) source); source = Arrays.asList(strings);
} }
if (source instanceof List) { if (source instanceof List<?> list) {
source = ((List<?>) source).stream().map(it -> convertOnRead(propertyValueConverter, it)) source = list.stream().map(it -> convertOnRead(propertyValueConverter, it))
.collect(Collectors.toList()); .collect(Collectors.toList());
} else if (source instanceof Set) { } else if (source instanceof Set<?> set) {
source = ((Set<?>) source).stream().map(it -> convertOnRead(propertyValueConverter, it)) source = set.stream().map(it -> convertOnRead(propertyValueConverter, it))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} else { } else {
source = convertOnRead(propertyValueConverter, source); source = convertOnRead(propertyValueConverter, source);

View File

@ -17,7 +17,6 @@ package org.springframework.data.elasticsearch.repository.query.parser;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.geo.GeoBox; import org.springframework.data.elasticsearch.core.geo.GeoBox;
@ -44,6 +43,7 @@ import org.springframework.lang.Nullable;
* @author Franck Marchand * @author Franck Marchand
* @author Artur Konczak * @author Artur Konczak
* @author Peter-Josef Meisch * @author Peter-Josef Meisch
* @author Junghoon Ban
*/ */
public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuery, CriteriaQuery> { public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuery, CriteriaQuery> {
@ -62,8 +62,8 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
@Override @Override
protected CriteriaQuery create(Part part, Iterator<Object> iterator) { protected CriteriaQuery create(Part part, Iterator<Object> iterator) {
PersistentPropertyPath<ElasticsearchPersistentProperty> path = context PersistentPropertyPath<ElasticsearchPersistentProperty> path = context.getPersistentPropertyPath(
.getPersistentPropertyPath(part.getProperty()); part.getProperty());
return new CriteriaQuery(from(part, return new CriteriaQuery(from(part,
new Criteria(path.toDotPath(ElasticsearchPersistentProperty.QueryPropertyToFieldNameConverter.INSTANCE)), new Criteria(path.toDotPath(ElasticsearchPersistentProperty.QueryPropertyToFieldNameConverter.INSTANCE)),
iterator)); iterator));
@ -74,8 +74,8 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
if (base == null) { if (base == null) {
return create(part, iterator); return create(part, iterator);
} }
PersistentPropertyPath<ElasticsearchPersistentProperty> path = context PersistentPropertyPath<ElasticsearchPersistentProperty> path = context.getPersistentPropertyPath(
.getPersistentPropertyPath(part.getProperty()); part.getProperty());
return base.addCriteria(from(part, return base.addCriteria(from(part,
new Criteria(path.toDotPath(ElasticsearchPersistentProperty.QueryPropertyToFieldNameConverter.INSTANCE)), new Criteria(path.toDotPath(ElasticsearchPersistentProperty.QueryPropertyToFieldNameConverter.INSTANCE)),
iterator)); iterator));
@ -109,8 +109,7 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
return criteria.is(parameters.next()).not(); return criteria.is(parameters.next()).not();
case REGEX: case REGEX:
return criteria.expression(parameters.next().toString()); return criteria.expression(parameters.next().toString());
case LIKE: case LIKE, STARTING_WITH:
case STARTING_WITH:
return criteria.startsWith(parameters.next().toString()); return criteria.startsWith(parameters.next().toString());
case ENDING_WITH: case ENDING_WITH:
return criteria.endsWith(parameters.next().toString()); return criteria.endsWith(parameters.next().toString());
@ -118,13 +117,11 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
return criteria.contains(parameters.next().toString()); return criteria.contains(parameters.next().toString());
case GREATER_THAN: case GREATER_THAN:
return criteria.greaterThan(parameters.next()); return criteria.greaterThan(parameters.next());
case AFTER: case AFTER, GREATER_THAN_EQUAL:
case GREATER_THAN_EQUAL:
return criteria.greaterThanEqual(parameters.next()); return criteria.greaterThanEqual(parameters.next());
case LESS_THAN: case LESS_THAN:
return criteria.lessThan(parameters.next()); return criteria.lessThan(parameters.next());
case BEFORE: case BEFORE, LESS_THAN_EQUAL:
case LESS_THAN_EQUAL:
return criteria.lessThanEqual(parameters.next()); return criteria.lessThanEqual(parameters.next());
case BETWEEN: case BETWEEN:
return criteria.between(parameters.next(), parameters.next()); return criteria.between(parameters.next(), parameters.next());
@ -132,8 +129,7 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
return criteria.in(asArray(parameters.next())); return criteria.in(asArray(parameters.next()));
case NOT_IN: case NOT_IN:
return criteria.notIn(asArray(parameters.next())); return criteria.notIn(asArray(parameters.next()));
case SIMPLE_PROPERTY: case SIMPLE_PROPERTY, WITHIN: {
case WITHIN: {
Object firstParameter = parameters.next(); Object firstParameter = parameters.next();
Object secondParameter = null; Object secondParameter = null;
if (type == Part.Type.SIMPLE_PROPERTY) { if (type == Part.Type.SIMPLE_PROPERTY) {
@ -154,40 +150,24 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
secondParameter = parameters.next(); secondParameter = parameters.next();
} }
if (firstParameter instanceof GeoPoint && secondParameter instanceof String) return doWithinIfPossible(criteria, firstParameter, secondParameter);
return criteria.within((GeoPoint) firstParameter, (String) secondParameter);
if (firstParameter instanceof Point && secondParameter instanceof Distance)
return criteria.within((Point) firstParameter, (Distance) secondParameter);
if (firstParameter instanceof String && secondParameter instanceof String)
return criteria.within((String) firstParameter, (String) secondParameter);
} }
case NEAR: { case NEAR: {
Object firstParameter = parameters.next(); Object firstParameter = parameters.next();
if (firstParameter instanceof GeoBox) { if (firstParameter instanceof GeoBox geoBox) {
return criteria.boundedBy((GeoBox) firstParameter); return criteria.boundedBy(geoBox);
} }
if (firstParameter instanceof Box) { if (firstParameter instanceof Box box) {
return criteria.boundedBy(GeoBox.fromBox((Box) firstParameter)); return criteria.boundedBy(GeoBox.fromBox(box));
} }
Object secondParameter = parameters.next(); Object secondParameter = parameters.next();
// "near" query can be the same query as the "within" query return doWithinIfPossible(criteria, firstParameter, secondParameter);
if (firstParameter instanceof GeoPoint && secondParameter instanceof String)
return criteria.within((GeoPoint) firstParameter, (String) secondParameter);
if (firstParameter instanceof Point && secondParameter instanceof Distance)
return criteria.within((Point) firstParameter, (Distance) secondParameter);
if (firstParameter instanceof String && secondParameter instanceof String)
return criteria.within((String) firstParameter, (String) secondParameter);
} }
case EXISTS: case EXISTS, IS_NOT_NULL:
case IS_NOT_NULL:
return criteria.exists(); return criteria.exists();
case IS_NULL: case IS_NULL:
return criteria.not().exists(); return criteria.not().exists();
@ -200,6 +180,32 @@ public class ElasticsearchQueryCreator extends AbstractQueryCreator<CriteriaQuer
} }
} }
/**
* Do a within query if possible, otherwise return the criteria unchanged.
*
* @param criteria must not be {@literal null}
* @param firstParameter must not be {@literal null}
* @param secondParameter must not be {@literal null}
* @return the criteria with the within query applied if possible.
* @author Junghoon Ban
*/
private Criteria doWithinIfPossible(Criteria criteria, Object firstParameter, Object secondParameter) {
if (firstParameter instanceof GeoPoint geoPoint && secondParameter instanceof String string) {
return criteria.within(geoPoint, string);
}
if (firstParameter instanceof Point point && secondParameter instanceof Distance distance) {
return criteria.within(point, distance);
}
if (firstParameter instanceof String firstString && secondParameter instanceof String secondString) {
return criteria.within(firstString, secondString);
}
return criteria;
}
private Object[] asArray(Object o) { private Object[] asArray(Object o) {
if (o instanceof Collection) { if (o instanceof Collection) {
return ((Collection<?>) o).toArray(); return ((Collection<?>) o).toArray();