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 org.everit.osgi.bundles.org.thymeleaf.thymeleaf Show documentation
Show all versions of org.everit.osgi.bundles.org.thymeleaf.thymeleaf Show documentation
XML/XHTML/HTML5 template engine for Java
The newest version!
/*
* =============================================================================
*
* Copyright (c) 2011-2013, 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/bookean 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 + 10);
strBuilder.append(input.substring(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('\'');
strBuilder.append(' ');
strBuilder.append('+');
strBuilder.append(' ');
inLiteralSubstitutionInsertion = false;
}
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('+');
strBuilder.append(' ');
}
strBuilder.append('\'');
inLiteralSubstitutionInsertion = true;
}
if (c == TextLiteralExpression.DELIMITER) {
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();
}
}