/* * Copyright 2014 Martin Kouba * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.trimou.dropwizard.views; import static org.trimou.util.Checker.checkArgumentsNotNull; import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.Locale; import java.util.Map; import javax.ws.rs.WebApplicationException; import org.trimou.Mustache; import org.trimou.engine.MustacheEngine; import org.trimou.engine.MustacheEngineBuilder; import org.trimou.engine.config.EngineConfigurationKey; import org.trimou.engine.locator.ClassPathTemplateLocator; import org.trimou.exception.MustacheException; import org.trimou.util.Strings; import io.dropwizard.views.View; import io.dropwizard.views.ViewRenderer; /** * A Dropwizard {@link ViewRenderer} backed by Trimou. * <p> * Localized template files support is enabled by default, but could be disabled to improve performance. * * @author Martin Kouba * @see Builder */ public class TrimouViewRenderer implements ViewRenderer { public static final String DEFAULT_SUFFIX = "trimou"; private final MustacheEngine engine; private final String suffix; private final boolean hasLocalizedTemplates; /** * * @param engine * @param suffix * @param hasLocalizedTemplates */ private TrimouViewRenderer(MustacheEngine engine, String suffix, boolean hasLocalizedTemplates) { checkArgumentsNotNull(engine, suffix, hasLocalizedTemplates); this.engine = engine; this.suffix = suffix.startsWith(".") ? suffix : "." + suffix; this.hasLocalizedTemplates = hasLocalizedTemplates; } @Override public boolean isRenderable(View view) { return view.getTemplateName().endsWith(suffix); } @Override public void render(View view, Locale locale, OutputStream output) throws IOException, WebApplicationException { Mustache template = null; if (hasLocalizedTemplates && locale != null) { // First try the Locale template = engine.getMustache(getLocalizedTemplateName(view.getTemplateName(), locale.toString())); if (template == null) { // Then only the language template = engine.getMustache(getLocalizedTemplateName(view.getTemplateName(), locale.getLanguage())); } } if (template == null) { template = engine.getMustache(view.getTemplateName()); } if (template == null) { throw new FileNotFoundException("Template not found: " + view.getTemplateName()); } final Writer writer = new OutputStreamWriter(output, engine.getConfiguration().getStringPropertyValue(EngineConfigurationKey.DEFAULT_FILE_ENCODING)); try { template.render(writer, view); } catch (MustacheException e) { throw new IOException(e); } finally { writer.flush(); } } @Override public void configure(Map<String, String> options) { // No-op } @Override public String getSuffix() { return suffix; } private String getLocalizedTemplateName(String templateName, String localePart) { return Strings.removeSuffix(templateName, suffix) + "_" + localePart + suffix; } public static class Builder { private String suffix = DEFAULT_SUFFIX; private boolean hasLocalizedTemplates = true; public Builder setSuffix(String suffix) { this.suffix = suffix; return this; } public Builder setHasLocalizedTemplates(boolean hasLocalizedTemplates) { this.hasLocalizedTemplates = hasLocalizedTemplates; return this; } public TrimouViewRenderer build() { return build(MustacheEngineBuilder.newBuilder()); } public TrimouViewRenderer build(MustacheEngineBuilder builder) { // Locator for views builder.addTemplateLocator(ClassPathTemplateLocator.builder(10).setClassLoader(this.getClass().getClassLoader()).build()); // Locator for partials and template inheritance builder.addTemplateLocator(ClassPathTemplateLocator.builder(9).setClassLoader(this.getClass().getClassLoader()).setSuffix(suffix).build()); return build(builder.build()); } public TrimouViewRenderer build(MustacheEngine engine) { return new TrimouViewRenderer(engine, suffix, hasLocalizedTemplates); } } }