<commit_before>package com.ilscipio.scipio.ce.webapp.ftl.template;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.cache.UtilCache;
import org.ofbiz.base.util.collections.MapStack;
import org.ofbiz.base.util.template.FreeMarkerWorker;

import com.ilscipio.scipio.ce.webapp.ftl.context.ContextFtlUtil;
import com.ilscipio.scipio.ce.webapp.ftl.template.TemplateInvoker.InvokeOptions.InvokeMode;

import freemarker.core.Environment;
import freemarker.ext.util.WrapperTemplateModel;
import freemarker.template.Configuration;
import freemarker.template.ObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateDirectiveModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateScalarModel;

/**
 * Template invoker base class.
 * Invokes Freemarker template render in a separate render from
 * any current renderer, using options carried in the instance itself,
 * using methods such as Ofbiz's FreeMarkerWorker does, and contrary
 * to the Freemarker <code>?interpret</code> call which inlines
 * in the current renderer (and therefore poses restrictions).
 * <p>
 * This is needed to: 
 * 1) carry the compilation and invocation options around
 * 2) allow nested Freemarker template renders that behave like separate renders 
 *    (and not like inlined interprets like <code>?interpret</code> does)
 * 3) enable evaluating templates using <code>?string</code> operator from freemarker templates
 * 4) allow lazy compilation but that still gets cached
 * <p>
 * For invoking other templates from within an FTL template,
 * StringTemplateInvoker can be used which causes the
 * invocation through the toString() method when this
 * is wrapped in a StringModel by the ObjectWrapper.
 * <p>
 * NOTE: 2017-02: Currently, by default, this relies on BeansWrapper StringModel to call
 * the StringTemplateInvoker.toString() method to do the invocation from templates;
 * this is imperfect but allows consistent unwrapping/rewrapping without needing 
 * to modify the ObjectWrapper. HOWEVER this means we only support the "scalar" model for now.
 * <p>
 * TODO: in future should have a dedicated TemplateDirectiveModel + TemplateScalarModel hybrid + individuals
 * in order to be consistent with the <code>?interpret</code> directive behavior (but needs
 * special code for rewrapping in context, ideally ObjectWrapper.wrap override).
 * <p>
 * TODO?: this currently does not support lazy template compilation... don't see much need.
 */
public class TemplateInvoker {

    public static final String module = TemplateInvoker.class.getName();
    
    protected final TemplateSource templateSource;<commit_msg>Refs #1153 cms: TemplateInvoker: added FIXME explanation as to why ?has_content will not work on these variables... for time being, this works out because it was going to cause other problems anyway<commit_after>package com.ilscipio.scipio.ce.webapp.ftl.template;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.cache.UtilCache;
import org.ofbiz.base.util.collections.MapStack;
import org.ofbiz.base.util.template.FreeMarkerWorker;

import com.ilscipio.scipio.ce.webapp.ftl.context.ContextFtlUtil;
import com.ilscipio.scipio.ce.webapp.ftl.template.TemplateInvoker.InvokeOptions.InvokeMode;

import freemarker.core.Environment;
import freemarker.ext.util.WrapperTemplateModel;
import freemarker.template.Configuration;
import freemarker.template.ObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateDirectiveModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateScalarModel;

/**
 * Template invoker base class.
 * Invokes Freemarker template render in a separate render from
 * any current renderer, using options carried in the instance itself,
 * using methods such as Ofbiz's FreeMarkerWorker does, and contrary
 * to the Freemarker <code>?interpret</code> call which inlines
 * in the current renderer (and therefore poses restrictions).
 * <p>
 * This is needed to: 
 * 1) carry the compilation and invocation options around
 * 2) allow nested Freemarker template renders that behave like separate renders 
 *    (and not like inlined interprets like <code>?interpret</code> does)
 * 3) enable evaluating templates using <code>?string</code> operator from freemarker templates
 * 4) allow lazy compilation but that still gets cached
 * <p>
 * For invoking other templates from within an FTL template,
 * StringTemplateInvoker can be used which causes the
 * invocation through the toString() method when this
 * is wrapped in a StringModel by the ObjectWrapper.
 * <p>
 * NOTE: 2017-02: Currently, by default, this relies on BeansWrapper StringModel to call
 * the StringTemplateInvoker.toString() method to do the invocation from templates;
 * this is imperfect but allows consistent unwrapping/rewrapping without needing 
 * to modify the ObjectWrapper. HOWEVER this means we only support the "scalar" model for now.
 * <p>
 * FIXME: the reliance on BeansWrapper StringModel means that the bean does not support
 * the <code>?has_content</code> built-in. This is a limitation caused by the <code>?has_content</code>
 * built-in that is hardcoded and delegates to BeanModel.empty method (not overridden by StringModel),
 * which does not invoke the toString method for our invoker object.
 * This is works out, because <code>?has_content</code> usage on the direct variable would
 * cause double-rendering and performance problems.
 * Instead, templates should use <code>??</code> operator or force cast to string
 * using <code>?string</code> so it is unambiguous at which point the rendering will occur and
 * will only happen once.
 * <p>
 * TODO: in future should have a dedicated TemplateDirectiveModel + TemplateScalarModel hybrid + individuals
 * in order to be consistent with the <code>?interpret</code> directive behavior (but needs
 * special code for rewrapping in context, ideally ObjectWrapper.wrap override).
 * <p>
 * TODO?: this currently does not support lazy template compilation... don't see much need.
 */
public class TemplateInvoker {

    public static final String module = TemplateInvoker.class.getName();
    
    protected final TemplateSource templateSource;
{'fraction_non_alphanumeric': 0.07553003533568904, 'fraction_numerical': 0.0035335689045936395, 'mean_word_length': 5.192342752962626, 'pattern_counts': {'":': 0, '<': 40, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4234147', 'n_tokens_mistral': 1840, 'n_tokens_neox': 1781, 'n_words': 689}