use of org.springframework.data.repository.query.parser.PartTree.OrPart in project spring-data-keyvalue by spring-projects.
the class SpelQueryCreator method toPredicateExpression.
protected SpelExpression toPredicateExpression(PartTree tree) {
int parameterIndex = 0;
StringBuilder sb = new StringBuilder();
for (Iterator<OrPart> orPartIter = tree.iterator(); orPartIter.hasNext(); ) {
int partCnt = 0;
StringBuilder partBuilder = new StringBuilder();
OrPart orPart = orPartIter.next();
for (Iterator<Part> partIter = orPart.iterator(); partIter.hasNext(); ) {
Part part = partIter.next();
if (!requiresInverseLookup(part)) {
partBuilder.append("#it?.");
partBuilder.append(part.getProperty().toDotPath().replace(".", "?."));
}
// TODO: check if we can have caseinsensitive search
if (!part.shouldIgnoreCase().equals(IgnoreCaseType.NEVER)) {
throw new InvalidDataAccessApiUsageException("Ignore case not supported!");
}
switch(part.getType()) {
case TRUE:
partBuilder.append("?.equals(true)");
break;
case FALSE:
partBuilder.append("?.equals(false)");
break;
case SIMPLE_PROPERTY:
partBuilder.append("?.equals(").append("[").append(parameterIndex++).append("])");
break;
case IS_NULL:
partBuilder.append(" == null");
break;
case IS_NOT_NULL:
partBuilder.append(" != null");
break;
case LIKE:
partBuilder.append("?.contains(").append("[").append(parameterIndex++).append("])");
break;
case STARTING_WITH:
partBuilder.append("?.startsWith(").append("[").append(parameterIndex++).append("])");
break;
case AFTER:
case GREATER_THAN:
partBuilder.append(">").append("[").append(parameterIndex++).append("]");
break;
case GREATER_THAN_EQUAL:
partBuilder.append(">=").append("[").append(parameterIndex++).append("]");
break;
case BEFORE:
case LESS_THAN:
partBuilder.append("<").append("[").append(parameterIndex++).append("]");
break;
case LESS_THAN_EQUAL:
partBuilder.append("<=").append("[").append(parameterIndex++).append("]");
break;
case ENDING_WITH:
partBuilder.append("?.endsWith(").append("[").append(parameterIndex++).append("])");
break;
case BETWEEN:
int index = partBuilder.lastIndexOf("#it?.");
partBuilder.insert(index, "(");
partBuilder.append(">").append("[").append(parameterIndex++).append("]");
partBuilder.append("&&");
partBuilder.append("#it?.");
partBuilder.append(part.getProperty().toDotPath().replace(".", "?."));
partBuilder.append("<").append("[").append(parameterIndex++).append("]");
partBuilder.append(")");
break;
case REGEX:
partBuilder.append(" matches ").append("[").append(parameterIndex++).append("]");
break;
case IN:
partBuilder.append("[").append(parameterIndex++).append("].contains(");
partBuilder.append("#it?.");
partBuilder.append(part.getProperty().toDotPath().replace(".", "?."));
partBuilder.append(")");
break;
case CONTAINING:
case NOT_CONTAINING:
case NEGATING_SIMPLE_PROPERTY:
case EXISTS:
default:
throw new InvalidDataAccessApiUsageException(String.format("Found invalid part '%s' in query", part.getType()));
}
if (partIter.hasNext()) {
partBuilder.append("&&");
}
partCnt++;
}
if (partCnt > 1) {
sb.append("(").append(partBuilder).append(")");
} else {
sb.append(partBuilder);
}
if (orPartIter.hasNext()) {
sb.append("||");
}
}
return StringUtils.hasText(sb) ? PARSER.parseRaw(sb.toString()) : PARSER.parseRaw("true");
}
use of org.springframework.data.repository.query.parser.PartTree.OrPart in project spring-data-commons by spring-projects.
the class AbstractQueryCreator method createCriteria.
/**
* Actual query building logic. Traverses the {@link PartTree} and invokes callback methods to delegate actual
* criteria creation and concatenation.
*
* @param tree must not be {@literal null}.
* @return
*/
@Nullable
private S createCriteria(PartTree tree) {
S base = null;
Iterator<Object> iterator = parameters.map(ParameterAccessor::iterator).orElse(Collections.emptyIterator());
for (OrPart node : tree) {
Iterator<Part> parts = node.iterator();
if (!parts.hasNext()) {
throw new IllegalStateException(String.format("No part found in PartTree %s!", tree));
}
S criteria = create(parts.next(), iterator);
while (parts.hasNext()) {
criteria = and(parts.next(), criteria, iterator);
}
base = base == null ? criteria : or(base, criteria);
}
return base;
}
use of org.springframework.data.repository.query.parser.PartTree.OrPart in project spring-data-commons by spring-projects.
the class PartTreeUnitTests method parsesNestedSpecialUnicodeCharactersMixedWithRegularCharactersCorrectly_Korean.
// DATACMNS-363
@Test
public void parsesNestedSpecialUnicodeCharactersMixedWithRegularCharactersCorrectly_Korean() {
PartTree tree = new //
PartTree(//
"findBy" + "이름" + "And" + //
"OrderId" + "And" + // we use _ here to mark the beginning of a new property reference "이름"
"Nested_이름" + "Or" + //
"NestedOrderId" + "OrderBy" + "생일" + "Asc", DomainObjectWithSpecialChars.class);
Iterator<OrPart> parts = tree.iterator();
assertPartsIn(parts.next(), new Part[] { //
new Part("이름", DomainObjectWithSpecialChars.class), //
new Part("order.id", DomainObjectWithSpecialChars.class), //
new Part("nested.이름", DomainObjectWithSpecialChars.class) });
assertPartsIn(parts.next(), new Part[] { //
new Part("nested.order.id", DomainObjectWithSpecialChars.class) });
assertThat(tree.getSort().getOrderFor("생일").isAscending()).isTrue();
}
use of org.springframework.data.repository.query.parser.PartTree.OrPart in project spring-data-commons by spring-projects.
the class PartTreeUnitTests method assertPartsIn.
private void assertPartsIn(OrPart orPart, Part[] part) {
Iterator<Part> partIterator = orPart.iterator();
for (int k = 0; k < part.length; k++) {
assertThat(partIterator.hasNext()).as("Expected %d parts but have %d", part.length, k).isTrue();
Part next = partIterator.next();
assertThat(part[k]).as("Expected %s but got %s!", part[k], next).isEqualTo(next);
}
assertThat(partIterator.hasNext()).as("Too many parts!").isFalse();
}
use of org.springframework.data.repository.query.parser.PartTree.OrPart in project spring-data-commons by spring-projects.
the class PartTreeUnitTests method parsesNestedSpecialUnicodeCharactersMixedWithRegularCharactersCorrectly_KoreanNumbersSymbols.
// DATACMNS-363
@Test
public void parsesNestedSpecialUnicodeCharactersMixedWithRegularCharactersCorrectly_KoreanNumbersSymbols() {
PartTree tree = new //
PartTree(//
"findBy" + "이름" + "And" + //
"OrderId" + "And" + //
"Anders" + "And" + //
"Property1" + "And" + //
"Øre" + "And" + //
"År" + "Or" + //
"NestedOrderId" + "And" + // we use _ here to mark the beginning of a new property reference "이름"
"Nested_property1" + "And" + //
"Property1" + "OrderBy" + "생일" + "Asc", DomainObjectWithSpecialChars.class);
Iterator<OrPart> parts = tree.iterator();
assertPartsIn(parts.next(), new Part[] { //
new Part("이름", DomainObjectWithSpecialChars.class), //
new Part("order.id", DomainObjectWithSpecialChars.class), //
new Part("anders", DomainObjectWithSpecialChars.class), //
new Part("property1", DomainObjectWithSpecialChars.class), //
new Part("øre", DomainObjectWithSpecialChars.class), //
new Part("år", DomainObjectWithSpecialChars.class) });
assertPartsIn(parts.next(), new Part[] { //
new Part("nested.order.id", DomainObjectWithSpecialChars.class), //
new Part("nested.property1", DomainObjectWithSpecialChars.class), //
new Part("property1", DomainObjectWithSpecialChars.class) });
assertThat(tree.getSort().getOrderFor("생일").isAscending()).isTrue();
}
Aggregations