org.thymeleaf.engine.AbstractTextualTemplateEvent 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
The newest version!
/*
* =============================================================================
*
* Copyright (c) 2011-2018, 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.engine;
import java.io.IOException;
import java.io.Writer;
import org.thymeleaf.util.IWritableCharSequence;
/**
*
* @author Daniel Fernández
* @since 3.0.0
*
*/
abstract class AbstractTextualTemplateEvent extends AbstractTemplateEvent implements IEngineTemplateEvent {
private final CharSequence contentCharSeq;
private final String contentStr;
private final int contentLength;
private volatile String computedContentStr = null;
private volatile int computedContentLength = -1;
private volatile Boolean computedContentIsWhitespace = null;
private volatile Boolean computedContentIsInlineable = null;
AbstractTextualTemplateEvent(final CharSequence content) {
super();
this.contentCharSeq = content;
if (content != null && content instanceof String) {
this.contentStr = (String)content;
this.contentLength = content.length();
} else {
this.contentStr = null;
this.contentLength = -1;
}
}
AbstractTextualTemplateEvent(final CharSequence content, final String templateName, final int line, final int col) {
super(templateName, line, col);
this.contentCharSeq = content;
if (content != null && content instanceof String) {
this.contentStr = (String)content;
this.contentLength = content.length();
} else {
this.contentStr = null;
this.contentLength = -1;
}
}
protected final String getContentText() {
if (this.contentStr != null || this.contentCharSeq == null) {
return this.contentStr;
}
String t = this.computedContentStr;
if (t == null) {
this.computedContentStr = t = this.contentCharSeq.toString();
}
return t;
}
protected final int getContentLength() {
if (this.contentLength >= 0 || this.contentCharSeq == null) {
return this.contentLength;
}
int l = this.computedContentLength;
if (l < 0) {
this.computedContentLength = l = this.contentCharSeq.length();
}
return l;
}
protected final char charAtContent(final int index) {
// no need to perform index bounds checking: it would slow down traversing operations a lot, and
// it would be exactly the same exception we'd obtain by basically trying to access that index, so let's do
// it directly instead
if (this.contentStr != null) {
return this.contentStr.charAt(index);
}
if (this.computedContentStr != null) {
// Once the String is computed, this could be faster
return this.computedContentStr.charAt(index);
}
return this.contentCharSeq.charAt(index);
}
protected final CharSequence contentSubSequence(final int start, final int end) {
// no need to perform index bounds checking: it would slow down traversing operations a lot, and
// it would be exactly the same exception we'd obtain by basically trying to access that index, so let's do
// it directly instead
if (this.contentStr != null) {
return this.contentStr.subSequence(start, end);
}
if (this.computedContentStr != null) {
// Once the String is computed, this could be faster
return this.computedContentStr.subSequence(start, end);
}
return this.contentCharSeq.subSequence(start, end);
}
final boolean isWhitespace() {
Boolean w = this.computedContentIsWhitespace;
if (w == null) {
this.computedContentIsWhitespace = w = computeWhitespace();
}
return w.booleanValue();
}
final boolean isInlineable() {
Boolean i = this.computedContentIsInlineable;
if (i == null) {
this.computedContentIsInlineable = i = computeInlineable();
}
return i.booleanValue();
}
private Boolean computeWhitespace() {
int n = getContentLength(); // This will leave computedContentLength computed in case it's needed afterwards
if (n == 0) {
return Boolean.FALSE; // empty texts are NOT whitespace
}
char c;
while (n-- != 0) {
c = charAtContent(n);
if (c != ' ' && c != '\n') { // shortcut - most characters in many templates are just whitespace.
if (!Character.isWhitespace(c)) {
return Boolean.FALSE;
}
}
}
return Boolean.TRUE;
}
private Boolean computeInlineable() {
int n = getContentLength(); // This will leave computedContentLength computed in case it's needed afterwards
if (n == 0) {
return Boolean.FALSE;
}
char c0, c1;
c0 = 0x0;
int inline = 0;
while (n-- != 0) {
c1 = charAtContent(n);
if (n > 0 && c1 == ']' && c0 == ']') {
inline = 1;
n--;
c1 = charAtContent(n);
} else if (n > 0 && c1 == ')' && c0 == ']') {
inline = 2;
n--;
c1 = charAtContent(n);
} else if (inline == 1 && c1 == '[' && c0 == '[') {
return Boolean.TRUE;
} else if (inline == 2 && c1 == '[' && c0 == '(') {
return Boolean.TRUE;
}
c0 = c1;
}
return Boolean.FALSE;
}
public final void writeContent(final Writer writer) throws IOException {
if (this.contentStr != null) {
writer.write(this.contentStr);
} else if (this.computedContentStr != null) {
writer.write(this.computedContentStr);
} else if (this.contentCharSeq instanceof IWritableCharSequence) {
// In the special case we are using a writable CharSequence, we will avoid creating a String
// for the whole content
((IWritableCharSequence) this.contentCharSeq).write(writer);
} else {
writer.write(getContentText()); // We write, but make sure we cache the String we create
}
}
@Override
public String toString() {
return getContentText();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy