/* * Written by Yuchen Xie on 20120421 */ package mapx.java.soy; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.type.TypeReference; import com.google.common.io.Resources; import com.google.template.soy.data.SoyMapData; import com.google.template.soy.SoyFileSet; import com.google.template.soy.msgs.SoyMsgBundle; import com.google.template.soy.msgs.SoyMsgBundleHandler; import com.google.template.soy.tofu.SoyTofu; import com.google.template.soy.xliffmsgplugin.XliffMsgPlugin; import java.io.IOException; import java.util.HashMap; // jar file iterating import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; /** * Google closure template handler, the wraper to be called with jni methods. */ public final class SoyHandler { private final SoyTofu tofu; private static final HashMap msgBundleMap = new HashMap(); private static final ObjectMapper mapper = new ObjectMapper(); private static final TypeReference> typeRef = new TypeReference>(){}; /** * Render a template with json template name, json data and locale name. * @param tplName Template name that starts with dot as written in soy templates. * @param jsonMap JSON string that contains data used in the template. * @param locale Locale string, "" for default. * @return Template String rendered with data in jsonMap. * @throws IOException If there is an error reading jsonMap String. */ public String renderToString(String tplName, String jsonMap, String locale) throws IOException { HashMap data = mapper.readValue(jsonMap, typeRef); return tofu.newRenderer(tplName).setData(data) .setMsgBundle(msgBundleMap.get(locale)) .setIjData(new SoyMapData("locale", locale, "tplName", tplName, "data", data))// DEBUG tool .render(); } /** * Build SoyTofu variable with templates, translations and global_params.txt from this resource jar package. * @param resNamespace Namespace these SoyTofu resources in. * @throws IOException If there is an error parsing this jar file and open its resources. */ public SoyHandler(String resNamespace) throws IOException { String dir = resNamespace + "/templates"; SoyFileSet.Builder sfsBuilder = SoyFileSet.builder(); String jar = SoyHandler.class.getProtectionDomain().getCodeSource().getLocation().getFile(); JarFile jf = new JarFile(jar); Enumeration es = jf.entries(); while (es.hasMoreElements()) { String resname = es.nextElement().getName(); if (resname.startsWith(dir)) { if (resname.endsWith(".soy")) { //soy files are the templates System.out.println(resname); sfsBuilder.add(Resources.getResource(resname)); } else if (resname.endsWith(".xlf")) { // xlf files are the translations String xlfLocale = resname.substring(resname.lastIndexOf("/") + 1, resname.lastIndexOf(".")); System.out.println(xlfLocale); SoyMsgBundleHandler msgBundleHandler = new SoyMsgBundleHandler(new XliffMsgPlugin()); SoyMsgBundle msgBundle = msgBundleHandler.createFromResource(Resources.getResource(resname)); msgBundleMap.put(xlfLocale, msgBundle); } } } jf.close(); // and finally a global_params.txt for global params used in all templates. tofu = sfsBuilder.setCompileTimeGlobals(Resources.getResource(dir + "/global_params.txt")) .build().compileToTofu().forNamespace(resNamespace); } /** * This function stuff an empty string to a jni string outside JVM and simplify ReleaseStringChars calls. * @return String("ok") */ public String init() { return new String("ok"); } }