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

org.thymeleaf.processor.attr.AbstractFragmentInclusionAttrProcessor 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.processor.attr;

import java.util.ArrayList;
import java.util.List;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

import org.thymeleaf.Arguments;
import org.thymeleaf.ParsedTemplate;
import org.thymeleaf.exceptions.AttrProcessorException;
import org.thymeleaf.templateresolver.TemplateResolution;
import org.thymeleaf.util.FragmentUtils;
import org.thymeleaf.util.Validate;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * 
 * @author Daniel Fernández
 * 
 * @since 1.0
 *
 */
public abstract class AbstractFragmentInclusionAttrProcessor 
        extends AbstractChildrenModifierAttrProcessor {

    
    
    
    public AbstractFragmentInclusionAttrProcessor() {
        super();
    }



    
    
    
    @Override
    protected final List getNewChildren(
            final Arguments arguments, final TemplateResolution templateResolution, 
            final Document document, final Element element, 
            final Attr attribute, final String attributeName, final String attributeValue) {
        

        final AbstractFragmentSpec fragmentSpec =
            getFragmentSpec(arguments, templateResolution, document, element, attribute, attributeName, attributeValue);
        if (fragmentSpec == null) {
            throw new AttrProcessorException("Null value for \"" +
                        attribute.getName() + "\" fragment specification not allowed");
        }
        
        
        final Node fragmentNode = 
            getFragment(arguments, templateResolution, document, element, attribute, fragmentSpec); 
        
        if (fragmentNode == null) {
            throw new AttrProcessorException(
                    "An error happened during parsing of include: \"" + attributeValue + "\": fragment node is null");
        }

        try {
            
            // Imports the nodes from the fragment document to the template one
            final Node node = document.importNode(fragmentNode, true);
            
            final List children = new ArrayList();
            final NodeList nodeList = node.getChildNodes();
            for (int i = 0; i < nodeList.getLength(); i++) {
                children.add(nodeList.item(i));
            }
            
            return children;
            
        } catch (final Exception e) {
            throw new AttrProcessorException(
                    "An error happened during parsing of include: \"" + attributeValue + "\"", e);
        }
        
    }

    
    
    private static Node getFragment(
            final Arguments arguments, final TemplateResolution templateResolution, 
            final Document document, final Element element, 
            final Attr attribute, final AbstractFragmentSpec fragmentSpec) {

        
        final String fragmentTemplateName = fragmentSpec.getFragmentTemplateName();
        
        if (arguments.getTemplateName().equals(fragmentTemplateName)) {
            throw new AttrProcessorException(
                    "Template \"" + arguments.getTemplateName() + 
                    " references itself from a " +
                    "\"" + attribute.getName() + "\" attribute, which is forbidden.");
        }
        
        try {
            
            final Arguments fragmentArguments = 
                new Arguments(
                        arguments.getConfiguration(), 
                        arguments.getTemplateParser(), 
                        fragmentTemplateName, 
                        arguments.getContext(),
                        arguments.getLocalVariables(),
                        arguments.getSelectionTarget(),
                        arguments.getIdCounts(),
                        arguments.getTextInliner());
            
            final ParsedTemplate parsedTemplate = arguments.getTemplateParser().parseDocument(fragmentArguments);
            
            Node fragmentNode = null; 
            if (fragmentSpec instanceof NamedFragmentSpec) {
                
                final NamedFragmentSpec namedFragmentSpec = (NamedFragmentSpec) fragmentSpec;
                final String fragmentAttributeName = namedFragmentSpec.getFragmentAttributeName();
                final String fragmentAttributeValue = namedFragmentSpec.getFragmentAttributeValue();
                
                fragmentNode = 
                    FragmentUtils.extractFragmentByAttributevalue(parsedTemplate.getDocument(), fragmentAttributeName, fragmentAttributeValue);
                                        
                if (fragmentNode == null) {
                    throw new AttrProcessorException(
                            "Fragment \"" + fragmentAttributeValue + "\" in template \"" + fragmentTemplateName + "\" could not be found");
                }
                
            } else if (fragmentSpec instanceof CompleteTemplateFragmentSpec) {
                
                fragmentNode = parsedTemplate.getDocument().getDocumentElement();
                
                if (fragmentNode == null) {
                    throw new AttrProcessorException(
                            "Root node in template \"" + fragmentTemplateName + "\" could not be found");
                }
                
            } else if (fragmentSpec instanceof XPathFragmentSpec) {

                final XPathFragmentSpec xpathFragmentSpec = (XPathFragmentSpec) fragmentSpec;
                
                final XPath xpath = XPathFactory.newInstance().newXPath();
                final XPathExpression xpathExpr = xpath.compile(xpathFragmentSpec.getXPathExpression());
                
                final NodeList exprResult = 
                    (NodeList) xpathExpr.evaluate(parsedTemplate.getDocument(), XPathConstants.NODESET);
                
                fragmentNode = exprResult.item(0);
                
                if (fragmentNode == null) {
                    throw new AttrProcessorException(
                            "No result for XPath expression \"" + xpathFragmentSpec.getXPathExpression() +"\" in template \"" + fragmentTemplateName + "\" could be found");
                }
                
            }
            
            return fragmentNode;
        
        } catch (final AttrProcessorException e) {
            throw e;
        } catch (final Exception e) {
            throw new AttrProcessorException(
                    "An error happened during parsing of template: \"" + fragmentTemplateName + "\"", e);
        }
        
    }




    protected abstract AbstractFragmentSpec getFragmentSpec(
            final Arguments arguments, final TemplateResolution templateResolution, 
            final Document document, final Element element, 
            final Attr attribute, final String attributeName, final String attributeValue);
    


    
    /**
     * 
     * @author Daniel Fernández
     * 
     * @since 1.0
     *
     */
    protected static abstract class AbstractFragmentSpec {
        
        private final String fragmentTemplateName;
        
        
        public AbstractFragmentSpec(final String fragmentTemplateName) {
            super();
            Validate.notEmpty(fragmentTemplateName, "Fragment template name cannot be null or empty");
            this.fragmentTemplateName = fragmentTemplateName;
        }


        public String getFragmentTemplateName() {
            return this.fragmentTemplateName;
        }

    }


    
    /**
     * 
     * @author Daniel Fernández
     * 
     * @since 1.0
     *
     */
    protected static final class NamedFragmentSpec extends AbstractFragmentSpec {
        
        private final String fragmentAttributeName;
        private final String fragmentAttributeValue;
        
        
        public NamedFragmentSpec(final String fragmentTemplateName,
                final String fragmentAttributeName, final String fragmentAttributeValue) {
            super(fragmentTemplateName);
            Validate.notEmpty(fragmentAttributeName, "Fragment attribute name cannot be null or empty");
            Validate.notEmpty(fragmentAttributeValue, "Fragment attribute value cannot be null or empty");
            this.fragmentAttributeName = fragmentAttributeName;
            this.fragmentAttributeValue = fragmentAttributeValue;
        }


        public String getFragmentAttributeName() {
            return this.fragmentAttributeName;
        }


        public String getFragmentAttributeValue() {
            return this.fragmentAttributeValue;
        }
        
    }


    
    /**
     * 
     * @author Daniel Fernández
     * 
     * @since 1.0
     *
     */
    protected static final class CompleteTemplateFragmentSpec extends AbstractFragmentSpec {
        
        public CompleteTemplateFragmentSpec(final String fragmentTemplateName) {
            super(fragmentTemplateName);
        }

    }


    
    /**
     * 
     * @author Daniel Fernández
     * 
     * @since 1.0
     *
     */
    protected static final class XPathFragmentSpec extends AbstractFragmentSpec {
        
        private final String xpathExpression;

        public XPathFragmentSpec(final String fragmentTemplateName, 
                final String xpathExpression) {
            super(fragmentTemplateName);
            Validate.notEmpty(xpathExpression, "XPath expression cannot be null or empty");
            this.xpathExpression = xpathExpression;
        }
        
        public String getXPathExpression() {
            return this.xpathExpression;
        }
        

    }
    
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy