1 package net.pterodactylus.sone.template;
4 import java.io.FileInputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.io.InputStreamReader;
10 import java.util.ArrayList;
11 import java.util.Iterator;
12 import java.util.List;
13 import java.util.concurrent.atomic.AtomicReference;
15 import net.pterodactylus.util.template.Part;
16 import net.pterodactylus.util.template.Template;
17 import net.pterodactylus.util.template.TemplateContext;
18 import net.pterodactylus.util.template.TemplateException;
19 import net.pterodactylus.util.template.TemplateParser;
21 import com.google.common.base.Charsets;
24 * {@link Template} implementation that can be reloaded from the filesystem.
26 public class FilesystemTemplate extends Template {
28 private final String filename;
29 private final AtomicReference<LastLoadedTemplate> lastTemplate = new AtomicReference<>();
30 private final TemplateContext initialContext = new TemplateContext();
31 private final List<Part> parts = new ArrayList<>();
33 public FilesystemTemplate(String filename) {
34 this.filename = filename;
38 public TemplateContext getInitialContext() {
40 return initialContext;
43 private void loadTemplate() {
44 File templateFile = new File(filename);
45 if (templateWasLoaded() && !templateFileHasBeenModifiedAfterLoading(templateFile)) {
48 try (InputStream templateInputStream = new FileInputStream(templateFile);
49 Reader templateReader = new InputStreamReader(templateInputStream, Charsets.UTF_8)) {
50 Template template = TemplateParser.parse(templateReader);
51 lastTemplate.set(new LastLoadedTemplate(template));
52 template.getInitialContext().mergeContext(initialContext);
53 for (Part part : parts) {
56 } catch (IOException e) {
57 throw new TemplateFileNotFoundException(filename);
61 private boolean templateWasLoaded() {
62 return lastTemplate.get() != null;
65 private boolean templateFileHasBeenModifiedAfterLoading(File templateFile) {
66 return templateFile.lastModified() > lastTemplate.get().getLoadTime();
70 public void add(Part part) {
73 lastTemplate.get().getTemplate().add(part);
77 public void render(TemplateContext templateContext, Writer writer) throws TemplateException {
79 lastTemplate.get().getTemplate().render(templateContext, writer);
83 public Iterator<Part> iterator() {
85 return lastTemplate.get().getTemplate().iterator();
89 public int getLine() {
91 return lastTemplate.get().getTemplate().getLine();
95 public int getColumn() {
97 return lastTemplate.get().getTemplate().getColumn();
100 private static class LastLoadedTemplate {
102 private final Template template;
103 private final long loadTime = System.currentTimeMillis();
105 private LastLoadedTemplate(Template template) {
106 this.template = template;
109 public Template getTemplate() {
113 public long getLoadTime() {
120 * Exception that signals that a template file could not be found.
122 public static class TemplateFileNotFoundException extends RuntimeException {
124 public TemplateFileNotFoundException(String filename) {