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

com.causecode.util.StringAsGspRenderer.groovy Maven / Gradle / Ivy

package com.causecode.util

import grails.gsp.PageRenderer
import grails.util.Environment
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory

/**
 * A utility bean to compile & render a simple string text as a GSP content.
 * Basically, this bean creates a gsp template for given string (if not available) to compile & then
 * uses the groovy page renderer engine to render that template.
 * To use this bean just inject def stringAsGspRenderer in controller, domain
 * or services like other dependency injection.
 * @see NucleusGrailsPlugin.groovy for bean registration
 * @author Shashank Agrawal
 * @since v0.3.1
 */
@SuppressWarnings(['JavaIoPackageAccess'])
class StringAsGspRenderer {

    private static final Log logger = LogFactory.getLog(this)

    private static final String TEMPLATE_CACHE_DIRECTORY_NAME
    private static final String TEMPLATE_CACHE_DIRECTORY_PATH
    private static final String APP_ROOT

    private Map pageTemplateURLCache = [:]

    // Groovy page template engine bean injected in NucleusGrailsPlugin.groovy
    PageRenderer groovyPageRenderer

    static {
        TEMPLATE_CACHE_DIRECTORY_NAME = 'template-cache'
        String catalinaHome = System.getenv('CATALINA_HOME')
        APP_ROOT = "$catalinaHome/webapps/ROOT/WEB-INF"

        // For supporting running of War using embedded container.
        TEMPLATE_CACHE_DIRECTORY_PATH = "$APP_ROOT/grails-app/views/$TEMPLATE_CACHE_DIRECTORY_NAME"

        if (!APP_ROOT || [Environment.DEVELOPMENT, Environment.TEST].contains(Environment.current)) {
            TEMPLATE_CACHE_DIRECTORY_PATH = "./grails-app/views/$TEMPLATE_CACHE_DIRECTORY_NAME"
        }

        File temporaryDirectoryPath = new File(TEMPLATE_CACHE_DIRECTORY_PATH)

        logger.debug "Temporary path for template directory: $temporaryDirectoryPath.absolutePath"

        if (!temporaryDirectoryPath.exists()) {
            boolean status = temporaryDirectoryPath.mkdirs()
            logger.debug "Created template cache directory with status: [$status]"
        }
    }

    void clearCache() {
        pageTemplateURLCache = [:]
    }

    /**
     * Used to cleanup all template cache created by this utility class at startup.
     */
    void cleanupTemplateCache() {
        logger.info 'cleanupTemplateCache'
    }

    /**
     * Used to cleanup the old version of any domain instance.
     * @param domainInstance The instance of any domain object with version field
     */
    void cleanupOldTemplate(Object domainInstance, String field) {
        if (!domainInstance || !domainInstance.id || !domainInstance.version) {
            logger.info "No older version to cleanup for $domainInstance"
            return
        }

        String pageID = getPageIdForDomain(domainInstance, field, true)
        File oldCacheFile = new File("$TEMPLATE_CACHE_DIRECTORY_PATH/_${pageID}.gsp")

        if (oldCacheFile.exists()) {
            logger.debug "Deleting old cache file: $oldCacheFile.absolutePath"
            oldCacheFile.delete()
        } else {
            logger.debug "Old cache file not exists: $oldCacheFile.absolutePath"
        }
    }

    /**
     * Used to generate a unique template id for a domain instance.
     * @param domainInstance The instance of any grails domain class to create id for.
     * @param field Field in the domain class for unique id
     * @param previousVersion Will create a id with lower version. Used to delete the older file.
     * @example User_14_2 for a instance of a domain class with id 14 & version 2.
     * If domain has not yet been persisted than current timestamp will be appended
     * to avoid the caching problem.
     */
    private String getPageIdForDomain(Object domainInstance, String field, boolean previousVersion = false) {
        StringBuilder pageID = new StringBuilder(domainInstance.class.simpleName.toLowerCase())
        pageID.append('_')
        pageID.append(field)
        pageID.append('_')

        if (domainInstance.id) {
            pageID.append(domainInstance.id.toString())
            pageID.append('_')
            if (previousVersion) {
                pageID.append((domainInstance.version - 1).toString())
            } else {
                pageID.append(domainInstance.version.toString())
            }
        } else {
            pageID.append(System.currentTimeMillis())
        }

        return pageID.toString()
    }

    void removeFromCache (Object domainInstance, String field) {
        removeFromCache(getPageIdForDomain(domainInstance, field))
    }

    /*
     * Used to remove a template from cache so new version of same template can be used.
     */
    void removeFromCache(String pageID) {
        pageTemplateURLCache.remove(pageID)
    }

    String render(String content, Map model) {
        render("cc${System.currentTimeMillis()}", content, model)
    }

    /**
     * Used to compile & render a given content binded with model as string.
     * @param pageId A unique pageId for the content to create a template.
     * @param content String content to compile & render as gsp.
     * @param model Model to be bind on the given content.
     * @return Compiled & converted string
     */
    String render(String pageID, String content, Map model) {
        clearCache()

        // Check if that template is already created & cached.
        String fileURL = pageTemplateURLCache.get(pageID)

        // If cached template URL not already exist
        if (!fileURL || !(new File(fileURL).exists())) {
            // Create the template path as in view folder
            File templateFile = new File("$TEMPLATE_CACHE_DIRECTORY_PATH/_${pageID}.gsp")
            // Write content to the file
            templateFile.text = content

            fileURL = templateFile.absolutePath
            pageTemplateURLCache.put(pageID, fileURL)
        }

        // Render content for new page.
        groovyPageRenderer.render([template: "/$TEMPLATE_CACHE_DIRECTORY_NAME/$pageID", model: model])
    }

    String renderFromDomain(Object domainInstance, String field, Map model) {
        render(getPageIdForDomain(domainInstance, field), domainInstance[field], model)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy