package ninja.mustache.template; import java.util.Map; import java.util.Map.Entry; import ninja.Context; import ninja.Result; import ninja.i18n.Lang; import ninja.i18n.Messages; import ninja.template.TemplateEngine; import org.slf4j.Logger; import com.google.common.base.CaseFormat; import com.google.common.base.Optional; import com.google.common.collect.Maps; /** * Default implementation of the TemplateEngine interface * * @author ra, kpacha */ public abstract class AbstractTemplateEngine implements TemplateEngine { protected Messages messages; protected Lang lang; protected Logger logger; /** * Just collect the properties and put them into a Map * * @param context * @param result * @return */ protected Map getTemplateProperties(Context context, Result result) { Map map = initializeTemplatePropertiesMap(result.getRenderable()); insertContextPath(context, map); insertLanguageProperty(context, result, map); insertSessionProperties(context, map); insertI18nProperties(context, result, map); insertFlashProperties(context, result, map); return map; } /** * Get an initialized map with the received object * * @param renderableResult * @return */ protected Map initializeTemplatePropertiesMap(Object renderableResult) { Map map; // if the object is null we simply render an empty map... if (renderableResult == null) { map = Maps.newHashMap(); } else if (renderableResult instanceof Map) { map = (Map) renderableResult; } else { map = createTemplatePropertiesMapAndInsert(renderableResult); } return map; } /** * Getting an arbitrary Object, put that into the root of the template * properties map * * If you are rendering something like Results.ok().render(new MyObject()) * Assume MyObject has a public String name field. * * You can then access the fields in the template like that: * {myObject.publicField} * * @param renderableResult * @return */ private Map createTemplatePropertiesMapAndInsert(Object renderableResult) { String realClassNameLowerCamelCase = CaseFormat.UPPER_CAMEL.to( CaseFormat.LOWER_CAMEL, renderableResult.getClass() .getSimpleName()); Map map = Maps.newHashMap(); map.put(realClassNameLowerCamelCase, renderableResult); return map; } /** * Put the context path into the map * * @param context * @param map */ protected void insertContextPath(Context context, Map map) { map.put("contextPath", context.getContextPath()); } /** * set language from framework. You can access it in the templates as {lang} * * @param context * @param result * @param map */ protected void insertLanguageProperty(Context context, Result result, Map map) { Optional<String> language = lang.getLanguage(context, Optional.of(result)); if (language.isPresent()) { map.put("lang", language.get()); } } /** * Put all entries of the session cookie to the map. You can access the * values by their key in the cookie * * @param context * @param map */ protected void insertSessionProperties(Context context, Map map) { if (!context.getSession().isEmpty()) { map.put("session", context.getSession().getData()); } } /** * Add the required key-values or deltas for i18n * * @param context * @param result * @param map */ abstract protected void insertI18nProperties(Context context, Result result, Map map); /** * Convenience method to translate possible flash scope keys. * * If you want to set messages with placeholders please do that in your * controller. We only can set simple messages. Eg. A message like * "errorMessage=my name is: {0}" => translate in controller and pass * directly. A message like " errorMessage=An error occurred" => use that as * errorMessage. * * get keys via {flash.KEYNAME} * * @param context * @param result * @param map */ protected void insertFlashProperties(Context context, Result result, Map map) { Map<String, String> translatedFlashCookieMap = Maps.newHashMap(); for (Entry<String, String> entry : context.getFlashScope() .getCurrentFlashCookieData().entrySet()) { String messageValue = null; Optional<String> messageValueOptional = messages.get( entry.getValue(), context, Optional.of(result)); if (!messageValueOptional.isPresent()) { messageValue = entry.getValue(); } else { messageValue = messageValueOptional.get(); } translatedFlashCookieMap.put(entry.getKey(), messageValue); } map.put("flash", translatedFlashCookieMap); } }