<commit_before>package com.floreysoft.jmte;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.floreysoft.jmte.ProcessListener.Action;
import com.floreysoft.jmte.message.DefaultErrorHandler;
import com.floreysoft.jmte.renderer.DefaultCollectionRenderer;
import com.floreysoft.jmte.renderer.DefaultIterableRenderer;
import com.floreysoft.jmte.renderer.DefaultMapRenderer;
import com.floreysoft.jmte.renderer.DefaultObjectRenderer;
import com.floreysoft.jmte.template.Compiler;
import com.floreysoft.jmte.template.InterpretedTemplate;
import com.floreysoft.jmte.template.Template;
import com.floreysoft.jmte.token.Token;
import com.floreysoft.jmte.util.Tool;
import com.floreysoft.jmte.util.Util;

/**
 * <p>
 * The template engine - <b>THIS IS WHERE YOU START LOOKING</b>.
 * </p>
 * 
 * <p>
 * Usually this is the only class you need calling
 * {@link #transform(String, Map)}. Like this
 * </p>
 * 
 * <pre>
 * Engine engine = new Engine();
 * String transformed = engine.transform(input, model);
 * </pre>
 * 
 * <p>
 * You have to provide the template input written in the template language and a
 * model from String to Object. Maybe like this
 * </p>
 * 
 * <pre>
 * String input = &quot;${name}&quot;;
 * Map&lt;String, Object&gt; model = new HashMap&lt;String, Object&gt;();
 * model.put(&quot;name&quot;, &quot;Minimal Template Engine&quot;);
 * Engine engine = new Engine();
 * String transformed = engine.transform(input, model);
 * assert (transformed.equals(&quot;Minimal Template Engine&quot;));
 * </pre>
 * 
 * where <code>input</code> contains the template and <code>model</code> the
 * model. <br>
 * 
 * @see ErrorHandler
 * @see Tool
 * @see Renderer
 * @see NamedRenderer
 * @see ModelAdaptor
 * @see ProcessListener
 */
public final class Engine {
	private String exprStartToken = "${";
	private String exprEndToken = "}";
	private double expansionSizeFactor = 2;
	private ErrorHandler errorHandler = new DefaultErrorHandler();
	private boolean useCompilation = false;
	private ModelAdaptor modelAdaptor = new DefaultModelAdaptor();

	// As classes will never be unloaded and are thus global, it might be a good idea to have
	// the templates in a static, shared location as well
	private final static Map<String, Template> compiledTemplates = new HashMap<String, Template>();

	private final Map<Class<?>, Renderer<?>> renderers = new HashMap<Class<?>, Renderer<?>>();
	private final Map<Class<?>, Renderer<?>> resolvedRendererCache = new HashMap<Class<?>, Renderer<?>>();

	private final Map<String, NamedRenderer> namedRenderers = new HashMap<String, NamedRenderer>();
	private final Map<Class<?>, Set<NamedRenderer>> namedRenderersForClass = new HashMap<Class<?>, Set<NamedRenderer>>();

	final List<ProcessListener> listeners = new ArrayList<ProcessListener>();

	/**
	 * Creates a new engine having <code>${</code> and <code>}</code> as start
	 * and end strings for expressions.
	 */
	public Engine() {
		init();
	}

	private void init() {
		registerRenderer(Object.class, new DefaultObjectRenderer());
		registerRenderer(Map.class, new DefaultMapRenderer());
		registerRenderer(Collection.class, new DefaultCollectionRenderer());
		registerRenderer(Iterable.class, new DefaultIterableRenderer());
	}

	/**
	 * Transforms a template into an expanded output using the given model.
	 * 
	 * @param template<commit_msg>Final changes for 2.0 release. Waiting for Daniels feedback.<commit_after>package com.floreysoft.jmte;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.floreysoft.jmte.ProcessListener.Action;
import com.floreysoft.jmte.message.DefaultErrorHandler;
import com.floreysoft.jmte.renderer.DefaultCollectionRenderer;
import com.floreysoft.jmte.renderer.DefaultIterableRenderer;
import com.floreysoft.jmte.renderer.DefaultMapRenderer;
import com.floreysoft.jmte.renderer.DefaultObjectRenderer;
import com.floreysoft.jmte.template.Compiler;
import com.floreysoft.jmte.template.InterpretedTemplate;
import com.floreysoft.jmte.template.Template;
import com.floreysoft.jmte.token.Token;
import com.floreysoft.jmte.util.Tool;
import com.floreysoft.jmte.util.Util;

/**
 * <p>
 * The template engine - <b>THIS IS WHERE YOU START LOOKING</b>.
 * </p>
 * 
 * <p>
 * Usually this is the only class you need calling
 * {@link #transform(String, Map)}. Like this
 * </p>
 * 
 * <pre>
 * Engine engine = new Engine();
 * String transformed = engine.transform(input, model);
 * </pre>
 * 
 * <p>
 * You have to provide the template input written in the template language and a
 * model from String to Object. Maybe like this
 * </p>
 * 
 * <pre>
 * String input = &quot;${name}&quot;;
 * Map&lt;String, Object&gt; model = new HashMap&lt;String, Object&gt;();
 * model.put(&quot;name&quot;, &quot;Minimal Template Engine&quot;);
 * Engine engine = new Engine();
 * String transformed = engine.transform(input, model);
 * assert (transformed.equals(&quot;Minimal Template Engine&quot;));
 * </pre>
 * 
 * where <code>input</code> contains the template and <code>model</code> the
 * model. <br>
 * 
 * <p>
 * Use {@link #setUseCompilation(boolean)} to switch on compilation mode. This
 * will compile the template into Java byte code before execution. Especially when the template
 * is used often this will speed up the execution by a factor between 2 and
 * 10. However, each compiled template results in a new class definition and a
 * new globally cached singleton instance of it.
 * </p>
 * 
 * @see ErrorHandler
 * @see Tool
 * @see Renderer
 * @see NamedRenderer
 * @see ModelAdaptor
 * @see ProcessListener
 */
public final class Engine {
	private String exprStartToken = "${";
	private String exprEndToken = "}";
	private double expansionSizeFactor = 2;
	private ErrorHandler errorHandler = new DefaultErrorHandler();
	private boolean useCompilation = false;
	private ModelAdaptor modelAdaptor = new DefaultModelAdaptor();

	// As classes will never be unloaded and are thus global, it might be a good
	// idea to have
	// the templates in a static, shared location as well
	private final static Map<String, Template> compiledTemplates = new HashMap<String, Template>();

	private final Map<Class<?>, Renderer<?>> renderers = new HashMap<Class<?>, Renderer<?>>();
	private final Map<Class<?>, Renderer<?>> resolvedRendererCache = new HashMap<Class<?>, Renderer<?>>();

	private final Map<String, NamedRenderer> namedRenderers = new HashMap<String, NamedRenderer>();
	private final Map<Class<?>, Set<NamedRenderer>> namedRenderersForClass = new HashMap<Class<?>, Set<NamedRenderer>>();

	final List<ProcessListener> listeners = new ArrayList<ProcessListener>();

	/**
	 * Creates a new engine having <code>${</code> and <code>}</code> as start
	 * and end strings for expressions.
	 */
	public Engine() {
		init();
	}

	private void init() {
		registerRenderer(Object.class, new DefaultObjectRenderer());
		registerRenderer(Map.class, new DefaultMapRenderer());
		registerRenderer(Collection.class, new DefaultCollectionRenderer());
		registerRenderer(Iterable.class, new DefaultIterableRenderer());
	}

	/**
	 * Transforms a template into an expanded output using the given model.
	 * 
	 * @param template
{'fraction_non_alphanumeric': 0.12397140159179819, 'fraction_numerical': 0.0009442870632672333, 'mean_word_length': 5.027642276422764, 'pattern_counts': {'":': 0, '<': 95, '<?xml version=': 0, '>': 95, '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': '1991439', 'n_tokens_mistral': 2243, 'n_tokens_neox': 2164, 'n_words': 661}