]> WPIA git - gigi.git/blob - src/org/cacert/gigi/output/template/Template.java
Move Template to another package for moving AST-classes out.
[gigi.git] / src / org / cacert / gigi / output / template / Template.java
1 package org.cacert.gigi.output.template;
2
3 import java.io.EOFException;
4 import java.io.File;
5 import java.io.FileInputStream;
6 import java.io.IOException;
7 import java.io.InputStreamReader;
8 import java.io.PrintWriter;
9 import java.io.Reader;
10 import java.net.URISyntaxException;
11 import java.net.URL;
12 import java.util.LinkedList;
13 import java.util.Map;
14 import java.util.regex.Matcher;
15 import java.util.regex.Pattern;
16
17 import org.cacert.gigi.DevelLauncher;
18 import org.cacert.gigi.Language;
19 import org.cacert.gigi.output.Outputable;
20
21 public class Template implements Outputable {
22         static class TemplateBlock implements Outputable {
23                 String[] contents;
24                 Outputable[] vars;
25
26                 public TemplateBlock(String[] contents, Outputable[] vars) {
27                         this.contents = contents;
28                         this.vars = vars;
29                 }
30
31                 @Override
32                 public void output(PrintWriter out, Language l, Map<String, Object> vars) {
33                         for (int i = 0; i < contents.length; i++) {
34                                 out.print(contents[i]);
35                                 if (i < this.vars.length) {
36                                         this.vars[i].output(out, l, vars);
37                                 }
38                         }
39                 }
40
41         }
42
43         TemplateBlock data;
44
45         long lastLoaded;
46         File source;
47
48         private static final Pattern IF_PATTERN = Pattern.compile(" ?if\\(\\$([^)]+)\\) ?\\{ ?");
49
50         public Template(URL u) {
51                 try {
52                         Reader r = new InputStreamReader(u.openStream(), "UTF-8");
53                         try {
54                                 if (u.getProtocol().equals("file") && DevelLauncher.DEVEL) {
55                                         source = new File(u.toURI());
56                                         lastLoaded = source.lastModified() + 1000;
57                                 }
58                         } catch (URISyntaxException e) {
59                                 e.printStackTrace();
60                         }
61                         data = parse(r);
62                         r.close();
63                 } catch (IOException e) {
64                         throw new Error(e);
65                 }
66         }
67
68         public Template(Reader r) {
69                 try {
70                         data = parse(r);
71                         r.close();
72                 } catch (IOException e) {
73                         throw new Error(e);
74                 }
75         }
76
77         private TemplateBlock parse(Reader r) throws IOException {
78                 LinkedList<String> splitted = new LinkedList<String>();
79                 LinkedList<Outputable> commands = new LinkedList<Outputable>();
80                 StringBuffer buf = new StringBuffer();
81                 int ch = r.read();
82                 outer: while (true) {
83                         while (!endsWith(buf, "<?")) {
84                                 if (ch == -1) {
85                                         break outer;
86                                 }
87                                 buf.append((char) ch);
88                                 ch = r.read();
89                         }
90                         buf.delete(buf.length() - 2, buf.length());
91                         splitted.add(buf.toString());
92                         buf.delete(0, buf.length());
93                         while (!endsWith(buf, "?>")) {
94                                 buf.append((char) ch);
95                                 ch = r.read();
96                                 if (ch == -1) {
97                                         throw new EOFException();
98                                 }
99                         }
100                         buf.delete(buf.length() - 2, buf.length());
101                         String com = buf.toString().replace("\n", "");
102                         buf.delete(0, buf.length());
103                         Matcher m = IF_PATTERN.matcher(com);
104                         if (m.matches()) {
105                                 final String variable = m.group(1);
106                                 final TemplateBlock body = parse(r);
107                                 commands.add(new Outputable() {
108
109                                         @Override
110                                         public void output(PrintWriter out, Language l, Map<String, Object> vars) {
111                                                 Object o = vars.get(variable);
112                                                 if (o instanceof Boolean && o == Boolean.TRUE) {
113                                                         body.output(out, l, vars);
114                                                 }
115                                         }
116                                 });
117                                 continue;
118                         }
119                         if (com.matches(" ?\\} ?")) {
120                                 break;
121                         }
122                         commands.add(parseCommand(com));
123                 }
124                 splitted.add(buf.toString());
125                 String[] contents = splitted.toArray(new String[splitted.size()]);
126                 Outputable[] vars = commands.toArray(new Outputable[commands.size()]);
127                 return new TemplateBlock(contents, vars);
128         }
129
130         private boolean endsWith(StringBuffer buf, String string) {
131                 return buf.length() >= string.length()
132                         && buf.substring(buf.length() - string.length(), buf.length()).equals(string);
133         }
134
135         private Outputable parseCommand(String s2) {
136                 if (s2.startsWith("=_")) {
137                         final String raw = s2.substring(2);
138                         return new Outputable() {
139
140                                 @Override
141                                 public void output(PrintWriter out, Language l, Map<String, Object> vars) {
142                                         out.print(l.getTranslation(raw));
143                                 }
144                         };
145                 } else if (s2.startsWith("=$")) {
146                         final String raw = s2.substring(2);
147                         return new Outputable() {
148
149                                 @Override
150                                 public void output(PrintWriter out, Language l, Map<String, Object> vars) {
151                                         outputVar(out, l, vars, raw);
152                                 }
153                         };
154                 } else if (s2.startsWith("=s,")) {
155                         String command = s2.substring(3);
156                         final LinkedList<String> store = new LinkedList<String>();
157                         while (command.startsWith("$")) {
158                                 int idx = command.indexOf(",");
159                                 store.add(command.substring(0, idx));
160                                 command = command.substring(idx + 1);
161                         }
162                         final String text = command;
163                         return new Outputable() {
164
165                                 @Override
166                                 public void output(PrintWriter out, Language l, Map<String, Object> vars) {
167                                         String[] parts = l.getTranslation(text).split("%s");
168                                         String[] myvars = store.toArray(new String[store.size()]);
169                                         out.print(parts[0]);
170                                         for (int j = 1; j < parts.length; j++) {
171                                                 outputVar(out, l, vars, myvars[j - 1].substring(1));
172                                                 out.print(parts[j]);
173                                         }
174                                 }
175                         };
176                 } else {
177                         System.out.println("Unknown processing instruction: " + s2);
178                 }
179                 return null;
180         }
181
182         public void output(PrintWriter out, Language l, Map<String, Object> vars) {
183                 if (source != null && DevelLauncher.DEVEL) {
184                         if (lastLoaded < source.lastModified()) {
185                                 try {
186                                         System.out.println("Reloading template.... " + source);
187                                         InputStreamReader r = new InputStreamReader(new FileInputStream(source), "UTF-8");
188                                         parse(r);
189                                         r.close();
190                                         lastLoaded = source.lastModified() + 1000;
191                                 } catch (IOException e) {
192                                         e.printStackTrace();
193                                 }
194                         }
195                 }
196                 data.output(out, l, vars);
197         }
198
199         private void outputVar(PrintWriter out, Language l, Map<String, Object> vars, String varname) {
200                 Object s = vars.get(varname);
201
202                 if (s == null) {
203                         System.out.println("Empty variable: " + varname);
204                 }
205                 if (s instanceof Outputable) {
206                         ((Outputable) s).output(out, l, vars);
207                 } else {
208                         out.print(s);
209                 }
210         }
211 }