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

org.zodiac.template.velocity.spring.view.servlet.ServletVelocityLayoutView Maven / Gradle / Ivy

The newest version!
package org.zodiac.template.velocity.spring.view.servlet;

import java.io.StringWriter;
import java.util.Locale;
import javax.servlet.http.HttpServletResponse;

import org.apache.velocity.Template;
import org.apache.velocity.context.Context;
import org.apache.velocity.exception.ResourceNotFoundException;

import org.springframework.core.NestedIOException;

public class ServletVelocityLayoutView extends ServletVelocityToolboxView {

    /*
     * The default {@link #setLayoutUrl(String) layout url}.
     */
    public static final String DEFAULT_LAYOUT_URL = "layout.vm";

    /*
     * The default {@link #setLayoutKey(String) layout key}.
     */
    public static final String DEFAULT_LAYOUT_KEY = "layout";

    /*
     * The default {@link #setScreenContentKey(String) screen content key}.
     */
    public static final String DEFAULT_SCREEN_CONTENT_KEY = "screen_content";

    private String layoutUrl = DEFAULT_LAYOUT_URL;

    private String layoutKey = DEFAULT_LAYOUT_KEY;

    private String screenContentKey = DEFAULT_SCREEN_CONTENT_KEY;

    public void setLayoutUrl(String layoutUrl) {
        this.layoutUrl = layoutUrl;
    }

    public void setLayoutKey(String layoutKey) {
        this.layoutKey = layoutKey;
    }

    public void setScreenContentKey(String screenContentKey) {
        this.screenContentKey = screenContentKey;
    }

    /**
     * Overrides {@code ServletVelocityView.checkTemplate()} to additionally check that both the layout template and the
     * screen content template can be loaded. Note that during rendering of the screen content, the layout template can
     * be changed which may invalidate any early checking done here.
     * 
     * @param locale {@link Locale}
     * @return existing
     */
    @Override
    public boolean checkResource(Locale locale) throws Exception {
        if (!super.checkResource(locale)) {
            return false;
        }

        try {
            // Check that we can get the template, even if we might subsequently get it again.
            getTemplate(this.layoutUrl);
            return true;
        } catch (ResourceNotFoundException ex) {
            throw new NestedIOException("Cannot find Velocity template for URL [" + this.layoutUrl
                + "]: Did you specify the correct resource loader path?", ex);
        } catch (Exception ex) {
            throw new NestedIOException("Could not load Velocity template for URL [" + this.layoutUrl + "]", ex);
        }
    }

    /**
     * Overrides the normal rendering process in order to pre-process the JSONContext, merging it with the screen template
     * into a single value (identified by the value of screenContentKey). The layout template is then merged with the
     * modified JSONContext in the super class.
     * 
     * @param context context
     * @param response http response
     */
    @Override
    protected void doRender(Context context, HttpServletResponse response) throws Exception {
        renderScreenContent(context);

        // Velocity context now includes any mappings that were defined
        // (via #set) in screen content template.
        // The screen template can overrule the layout by doing
        // #set( $layout = "MyLayout.vm" )
        String layoutUrlToUse = (String)context.get(this.layoutKey);
        if (layoutUrlToUse != null) {
            if (logger.isDebugEnabled()) {
                logger.debug("Screen content template has requested layout [" + layoutUrlToUse + "]");
            }
        } else {
            // No explicit layout URL given -> use default layout of this view.
            layoutUrlToUse = this.layoutUrl;
        }

        mergeTemplate(getTemplate(layoutUrlToUse), context, response);
    }

    /*
     * The resulting context contains any mappings from render, plus screen content.
     */
    private void renderScreenContent(Context velocityContext) throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("Rendering screen content template [" + getUrl() + "]");
        }

        StringWriter sw = new StringWriter();
        Template screenContentTemplate = getTemplate(getUrl());
        screenContentTemplate.merge(velocityContext, sw);

        // Put rendered content into Velocity context.
        velocityContext.put(this.screenContentKey, sw.toString());
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy