package rfx.server.util.template; import java.io.IOException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.lang3.exception.ExceptionUtils; import rfx.server.util.StringPool; import com.github.jknack.handlebars.Handlebars; import com.github.jknack.handlebars.Helper; import com.github.jknack.handlebars.Options; import com.github.jknack.handlebars.Template; import com.github.jknack.handlebars.io.FileTemplateLoader; import com.github.jknack.handlebars.io.TemplateLoader; import com.github.mustachejava.MustacheException; /** * the utility class for Handlebars.java template (See more at http://jknack.github.io/handlebars.java/) * * @author Trieu.nguyen * */ public class HandlebarsTemplateUtil { final static Map<String, Template> mustacheMap = new ConcurrentHashMap<>();//for hot deployment & update template final static String BASE_TEMPLATE_PATH = "resources/tpl/"; final static String TEMPLATE_SUFFIX = ".html"; final static TemplateLoader loader = new FileTemplateLoader(BASE_TEMPLATE_PATH, TEMPLATE_SUFFIX); final static Handlebars handlebars = new Handlebars(loader); final static AtomicBoolean isUsedCache = new AtomicBoolean(true);//TODO static { HandlebarsHelpers.register(handlebars); //when a field is evaluated as null or no value, catch the error here handlebars.registerHelperMissing(new Helper<Object>() { @Override public CharSequence apply(final Object context, final Options options) throws IOException { Template tpl = options.fn; String field = tpl.text(); System.err.println(field + " is (NULL value) or (NOT existed) or (not found public getter) at "+tpl.filename()); //TODO log error to somewhere for easily debugging return StringPool.BLANK; } }); } public static void refreshCache(){ mustacheMap.clear(); } public static void disableUsedCache(){ isUsedCache.set(false); } public static void enableUsedCache(){ isUsedCache.set(true); } public static Template getCompiledTemplate(String tplPath) throws IOException{ if(isUsedCache.get()){ Template tpl = mustacheMap.get(tplPath); if(tpl == null){ System.out.println("HandlebarsTemplateUtil.compile and set cache for template "+tplPath); tpl = handlebars.compile(tplPath); mustacheMap.put(tplPath, tpl); } return tpl; } else { System.out.println("HandlebarsTemplateUtil.compile template "+tplPath); return handlebars.compile(tplPath); } } public static void compileAndCache(String tplPath) throws IOException{ mustacheMap.put(tplPath, handlebars.compile(tplPath)); System.out.println("...HandlebarsTemplateUtil.compileAndCache template: "+tplPath); } public static String execute(String tplPath, Object model){ if(tplPath == null){ throw new IllegalArgumentException("tplPath is NULL"); } try { Template template = getCompiledTemplate(tplPath); return template.apply(model); } catch (MustacheException e) { StringBuilder s = new StringBuilder("Error:"); s.append(e.getMessage()); return s.toString(); } catch (Throwable e) { StringBuilder s = new StringBuilder("Error###"); s.append(e.getMessage()); s.append(" ### <br>\n StackTrace: ").append(ExceptionUtils.getStackTrace(e)); return s.toString(); } } }