org.thymeleaf.standard.expression.LiteralSubstitutionUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of thymeleaf Show documentation
Show all versions of thymeleaf Show documentation
Modern server-side Java template engine for both web and standalone environments
/*
* =============================================================================
*
* Copyright (c) 2011-2016, The THYMELEAF team (http://www.thymeleaf.org)
*
* 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 org.thymeleaf.standard.expression;
/**
*
* @author Daniel Fernández
* @since 2.1.0
*
*/
final class LiteralSubstitutionUtil {
private static final char LITERAL_SUBSTITUTION_DELIMITER = '|';
/*
* The goal here is to convert literal substitution expressions (|...|) into a concatenation of variable and/or
* literal expressions.
*
* Example:
*
* # ------------------------------------------------------------
* %CONTEXT
* onevar = 'Hello'
* twovar = 'World'
* # ------------------------------------------------------------
* %INPUT
* ...
* # ------------------------------------------------------------
* %OUTPUT
* Hello World
* # ------------------------------------------------------------
*
* For this, the input text is scanned before simple expressions are decomposed and they are replaced by a series
* of concatenations of literals and variables.
*
* So: |${onevar} ${twovar}| --> ${onevar} + ' ' + ${twovar}
*
* NOTE literal substitution expressions do not allow literals, numeric/boolean tokens, conditional expressions, etc.
*
*/
static String performLiteralSubstitution(final String input) {
if (input == null) {
return null;
}
StringBuilder strBuilder = null;
boolean inLiteralSubstitution = false;
boolean inLiteralSubstitutionInsertion = false;
int expLevel = 0;
boolean inLiteral = false;
boolean inNothing = true;
final int inputLen = input.length();
for (int i = 0; i < inputLen; i++) {
final char c = input.charAt(i);
if (c == LITERAL_SUBSTITUTION_DELIMITER && !inLiteralSubstitution && inNothing) {
if (strBuilder == null) {
strBuilder = new StringBuilder(inputLen + 20);
strBuilder.append(input,0,i);
}
inLiteralSubstitution = true;
} else if (c == LITERAL_SUBSTITUTION_DELIMITER && inLiteralSubstitution && inNothing) {
if (inLiteralSubstitutionInsertion) {
strBuilder.append('\'');
inLiteralSubstitutionInsertion = false;
}
inLiteralSubstitution = false;
} else if (inNothing &&
(c == VariableExpression.SELECTOR ||
c == SelectionVariableExpression.SELECTOR ||
c == MessageExpression.SELECTOR ||
c == LinkExpression.SELECTOR) &&
(i + 1 < inputLen && input.charAt(i+1) == SimpleExpression.EXPRESSION_START_CHAR)) {
// We are opening an expression
if (inLiteralSubstitution && inLiteralSubstitutionInsertion) {
strBuilder.append("\' + ");
inLiteralSubstitutionInsertion = false;
} else if (inLiteralSubstitution && i > 0 && input.charAt(i - 1) == SimpleExpression.EXPRESSION_END_CHAR) {
// This expression is right after another one, with no characters between them
strBuilder.append(" + \'\' + ");
}
if (strBuilder != null) {
strBuilder.append(c);
strBuilder.append(SimpleExpression.EXPRESSION_START_CHAR);
}
expLevel = 1;
i++; // This avoids the following '{', which we already know is there, to increment expLevel twice
inNothing = false;
} else if (expLevel == 1 && c == SimpleExpression.EXPRESSION_END_CHAR) {
// We are closing an expression
if (strBuilder != null) {
strBuilder.append(SimpleExpression.EXPRESSION_END_CHAR);
}
expLevel = 0;
inNothing = true;
} else if (expLevel > 0 && c == SimpleExpression.EXPRESSION_START_CHAR) {
// We are in an expression. This is needed for correct nesting/unnesting of expressions
if (strBuilder != null) {
strBuilder.append(SimpleExpression.EXPRESSION_START_CHAR);
}
expLevel++;
} else if (expLevel > 1 && c == SimpleExpression.EXPRESSION_END_CHAR) {
// We are in an expression. This is needed for correct nesting/unnesting of expressions
if (strBuilder != null) {
strBuilder.append(SimpleExpression.EXPRESSION_END_CHAR);
}
expLevel--;
} else if (expLevel > 0) {
// We are in an expression and not closing it, so just add the char
if (strBuilder != null) {
strBuilder.append(c);
}
} else if (inNothing && !inLiteralSubstitution &&
c == TextLiteralExpression.DELIMITER && !TextLiteralExpression.isDelimiterEscaped(input, i)) {
// We enter a first-level text literal. We should not process any |'s inside
inNothing = false;
inLiteral = true;
if (strBuilder != null) {
strBuilder.append(c);
}
} else if (inLiteral && !inLiteralSubstitution &&
c == TextLiteralExpression.DELIMITER && !TextLiteralExpression.isDelimiterEscaped(input, i)) {
inLiteral = false;
inNothing = true;
if (strBuilder != null) {
strBuilder.append(c);
}
} else if (inLiteralSubstitution && inNothing) {
// This char is not starting an expresion, but it is inside a literal substitution, so add it
// (and start an insertion if needed)
if (!inLiteralSubstitutionInsertion) {
if (input.charAt(i - 1) != LITERAL_SUBSTITUTION_DELIMITER) {
strBuilder.append(" + ");
}
strBuilder.append('\'');
inLiteralSubstitutionInsertion = true;
}
if (c == TextLiteralExpression.DELIMITER) {
strBuilder.append('\\');
} else if (c == TextLiteralExpression.ESCAPE_PREFIX) {
strBuilder.append('\\');
}
strBuilder.append(c);
} else {
// No literal substitution or anything. Just add the char
if (strBuilder != null) {
strBuilder.append(c);
}
}
}
if (strBuilder == null) {
return input;
}
return strBuilder.toString();
}
private LiteralSubstitutionUtil() {
super();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy