1 package org.cacert.gigi.output.template;
3 import java.io.EOFException;
5 import java.io.FileInputStream;
6 import java.io.IOException;
7 import java.io.InputStreamReader;
8 import java.io.PrintWriter;
10 import java.net.URISyntaxException;
12 import java.util.LinkedList;
14 import java.util.regex.Matcher;
15 import java.util.regex.Pattern;
17 import org.cacert.gigi.DevelLauncher;
18 import org.cacert.gigi.Language;
19 import org.cacert.gigi.output.Outputable;
21 public class Template implements Outputable {
27 private static final Pattern CONTROL_PATTERN = Pattern.compile(" ?([a-z]+)\\(\\$([^)]+)\\) ?\\{ ?");
29 public Template(URL u) {
31 Reader r = new InputStreamReader(u.openStream(), "UTF-8");
33 if (u.getProtocol().equals("file") && DevelLauncher.DEVEL) {
34 source = new File(u.toURI());
35 lastLoaded = source.lastModified() + 1000;
37 } catch (URISyntaxException e) {
42 } catch (IOException e) {
47 public Template(Reader r) {
51 } catch (IOException e) {
56 private TemplateBlock parse(Reader r) throws IOException {
57 LinkedList<String> splitted = new LinkedList<String>();
58 LinkedList<Outputable> commands = new LinkedList<Outputable>();
59 StringBuffer buf = new StringBuffer();
62 while (!endsWith(buf, "<?")) {
66 buf.append((char) ch);
69 buf.delete(buf.length() - 2, buf.length());
70 splitted.add(buf.toString());
71 buf.delete(0, buf.length());
72 while (!endsWith(buf, "?>")) {
73 buf.append((char) ch);
76 throw new EOFException();
79 buf.delete(buf.length() - 2, buf.length());
80 String com = buf.toString().replace("\n", "");
81 buf.delete(0, buf.length());
82 Matcher m = CONTROL_PATTERN.matcher(com);
84 String type = m.group(1);
85 String variable = m.group(2);
86 TemplateBlock body = parse(r);
87 if (type.equals("if")) {
88 commands.add(new IfStatement(variable, body));
89 } else if (type.equals("foreach")) {
90 commands.add(new ForeachStatement(variable, body));
92 throw new IOException("Syntax error: unknown control structure: " + type);
96 if (com.matches(" ?\\} ?")) {
99 commands.add(parseCommand(com));
101 splitted.add(buf.toString());
102 String[] contents = splitted.toArray(new String[splitted.size()]);
103 Outputable[] vars = commands.toArray(new Outputable[commands.size()]);
104 return new TemplateBlock(contents, vars);
107 private boolean endsWith(StringBuffer buf, String string) {
108 return buf.length() >= string.length()
109 && buf.substring(buf.length() - string.length(), buf.length()).equals(string);
112 private Outputable parseCommand(String s2) {
113 if (s2.startsWith("=_")) {
114 final String raw = s2.substring(2);
115 return new TranslateCommand(raw);
116 } else if (s2.startsWith("=$")) {
117 final String raw = s2.substring(2);
118 return new OutputVariableCommand(raw);
119 } else if (s2.startsWith("=s,")) {
120 String command = s2.substring(3);
121 final LinkedList<String> store = new LinkedList<String>();
122 while (command.startsWith("$")) {
123 int idx = command.indexOf(",");
124 store.add(command.substring(0, idx));
125 command = command.substring(idx + 1);
127 final String text = command;
128 return new SprintfCommand(text, store);
130 System.out.println("Unknown processing instruction: " + s2);
135 public void output(PrintWriter out, Language l, Map<String, Object> vars) {
136 if (source != null && DevelLauncher.DEVEL) {
137 if (lastLoaded < source.lastModified()) {
139 System.out.println("Reloading template.... " + source);
140 InputStreamReader r = new InputStreamReader(new FileInputStream(source), "UTF-8");
143 lastLoaded = source.lastModified() + 1000;
144 } catch (IOException e) {
149 data.output(out, l, vars);
152 protected static void outputVar(PrintWriter out, Language l, Map<String, Object> vars, String varname) {
153 Object s = vars.get(varname);
156 System.out.println("Empty variable: " + varname);
158 if (s instanceof Outputable) {
159 ((Outputable) s).output(out, l, vars);