All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.thymeleaf.DOMDocumentPreprocessor Maven / Gradle / Ivy

Go to download

Modern server-side Java template engine for both web and standalone environments

There is a newer version: 3.1.3.RELEASE
Show newest version
/*
 * =============================================================================
 * 
 *   Copyright (c) 2011, 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;

import java.util.Set;

import org.thymeleaf.exceptions.ParsingException;
import org.thymeleaf.processor.attr.IAttrProcessor;
import org.thymeleaf.processor.tag.ITagProcessor;
import org.thymeleaf.util.Validate;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;




/**
 * 

* Preprocess template DOM, setting executability flags where required. *

*

* During cache storage of a template, all nodes in the template's DOM are scanned * in order to detect which ones the engine can safely skip during normal operation, and * flags are set consequently. *

* * @author Daniel Fernández * * @since 1.1 * */ final class DOMDocumentPreprocessor { /** *

* Preprocesses the (recently parsed) document, * setting executability flags as appropiate for each node. *

* * @param configuration the configuration currently being used for the Template Engine. * @param document the document to be preprocessed */ static void preprocess( final Configuration configuration, final Document document) { Validate.notNull(configuration, "Configuration cannot be null"); Validate.notNull(document, "Document cannot be null"); Element rootElement = null; final NodeList docChildren = document.getChildNodes(); if (docChildren.getLength() < 1) { throw new ParsingException( "Invalid document structure: no root element found."); } if (docChildren.getLength() == 1) { rootElement = (Element) docChildren.item(0); } else if (docChildren.getLength() >= 2) { for (int i = 1; rootElement == null && i < docChildren.getLength(); i++) { if (docChildren.item(i).getNodeType() == Node.ELEMENT_NODE) { rootElement = (Element) docChildren.item(i); } } if (rootElement == null) { throw new ParsingException( "Invalid document structure: No valid root element found."); } } else { throw new ParsingException( "Invalid document structure: No more than two top-level elements are allowed " + "(either root element, or doctype + root element)."); } unsafePreprocessNode(configuration, rootElement); } private static boolean unsafePreprocessNode( final Configuration configuration, final Node node) { if (node.getNodeType() == Node.ELEMENT_NODE) { boolean isNodeExecutable = false; final Element element = (Element) node; final String elementName = element.getNodeName(); final Set dialectsForTagName = configuration.getDialectsForTagName(elementName); if (dialectsForTagName != null) { // This tag name is (potentially) processed by some of our dialects final ITagProcessor elementProcessor = configuration.getTagProcessor(dialectsForTagName, element); if (elementProcessor != null) { isNodeExecutable = true; } } if (!isNodeExecutable) { final NamedNodeMap attributes = element.getAttributes(); for (int i = 0; !isNodeExecutable && i < attributes.getLength(); i++) { final Attr attribute = (Attr) attributes.item(i); final String attributeName = attribute.getName(); final Set dialectsForAttrName = configuration.getDialectsForAttrName(attributeName); if (dialectsForAttrName != null) { // This attr name is (potentially) processed by some of our dialects final IAttrProcessor attrProcessor = configuration.getAttrProcessor(dialectsForAttrName, element, attribute); if (attrProcessor != null) { isNodeExecutable = true; } } } } if (!isNodeExecutable) { // We already know this node is not executable. DOMExecution.setExecutableNode(node, false); } /* * Scan the node's children */ boolean isTreeExecutable = isNodeExecutable; final NodeList children = node.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { if (unsafePreprocessNode(configuration, children.item(i))) { // Tree is executable when at least one child is executable isTreeExecutable = true; } } if (!isTreeExecutable) { // There is nothing to execute in this whole tree DOMExecution.setExecutableTree(node, false); } return isTreeExecutable; } /* * By default, any non-element node is non-executable. * * The only special case in which it could be executable is when an inliner has been * set for any of its parents. But in that case, the processor setting the inliner * should have cleared the "executability" flag for all the children of the * tag that the inliner is being set at. */ DOMExecution.setExecutableNode(node, false); return false; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy