1
16 package org.springframework.data.jpa.repository.query;
17
18 import java.util.regex.Pattern;
19
20 import org.springframework.data.repository.core.EntityMetadata;
21 import org.springframework.expression.Expression;
22 import org.springframework.expression.ParserContext;
23 import org.springframework.expression.spel.standard.SpelExpressionParser;
24 import org.springframework.expression.spel.support.StandardEvaluationContext;
25 import org.springframework.util.Assert;
26
27
39 class ExpressionBasedStringQuery extends StringQuery {
40
41 private static final String EXPRESSION_PARAMETER = "?#{";
42 private static final String QUOTED_EXPRESSION_PARAMETER = "?__HASH__{";
43
44 private static final Pattern EXPRESSION_PARAMETER_QUOTING = Pattern.compile(Pattern.quote(EXPRESSION_PARAMETER));
45 private static final Pattern EXPRESSION_PARAMETER_UNQUOTING = Pattern.compile(Pattern
46 .quote(QUOTED_EXPRESSION_PARAMETER));
47
48 private static final String ENTITY_NAME = "entityName";
49 private static final String ENTITY_NAME_VARIABLE = "#" + ENTITY_NAME;
50 private static final String ENTITY_NAME_VARIABLE_EXPRESSION = "#{" + ENTITY_NAME_VARIABLE + "}";
51
52
59 public ExpressionBasedStringQuery(String query, JpaEntityMetadata<?> metadata, SpelExpressionParser parser) {
60 super(renderQueryIfExpressionOrReturnQuery(query, metadata, parser));
61 }
62
63
71 static ExpressionBasedStringQuery from(DeclaredQuery query, JpaEntityMetadata metadata,
72 SpelExpressionParser parser) {
73 return new ExpressionBasedStringQuery(query.getQueryString(), metadata, parser);
74 }
75
76
82 private static String renderQueryIfExpressionOrReturnQuery(String query, JpaEntityMetadata<?> metadata,
83 SpelExpressionParser parser) {
84
85 Assert.notNull(query, "query must not be null!");
86 Assert.notNull(metadata, "metadata must not be null!");
87 Assert.notNull(parser, "parser must not be null!");
88
89 if (!containsExpression(query)) {
90 return query;
91 }
92
93 StandardEvaluationContext evalContext = new StandardEvaluationContext();
94 evalContext.setVariable(ENTITY_NAME, metadata.getEntityName());
95
96 query = potentiallyQuoteExpressionsParameter(query);
97
98 Expression expr = parser.parseExpression(query, ParserContext.TEMPLATE_EXPRESSION);
99
100 String result = expr.getValue(evalContext, String.class);
101
102 if (result == null) {
103 return query;
104 }
105
106 return potentiallyUnquoteParameterExpressions(result);
107 }
108
109 private static String potentiallyUnquoteParameterExpressions(String result) {
110 return EXPRESSION_PARAMETER_UNQUOTING.matcher(result).replaceAll(EXPRESSION_PARAMETER);
111 }
112
113 private static String potentiallyQuoteExpressionsParameter(String query) {
114 return EXPRESSION_PARAMETER_QUOTING.matcher(query).replaceAll(QUOTED_EXPRESSION_PARAMETER);
115 }
116
117 private static boolean containsExpression(String query) {
118 return query.contains(ENTITY_NAME_VARIABLE_EXPRESSION);
119 }
120 }
121