1 package club.wpia.gigi.output.template;
3 import java.io.PrintWriter;
4 import java.util.Arrays;
5 import java.util.Collection;
6 import java.util.HashMap;
7 import java.util.LinkedList;
10 import java.util.regex.Matcher;
11 import java.util.regex.Pattern;
13 import club.wpia.gigi.Gigi;
14 import club.wpia.gigi.localisation.Language;
15 import club.wpia.gigi.util.HTMLEncoder;
18 * A pattern that is to be translated before variables are inserted.
20 public final class SprintfCommand implements Translatable {
22 private final String text;
24 private final String[] store;
27 * Creates a new SprintfCommand based on its pre-parsed contents.
30 * a string with <code>{0},{1},..</code> as placeholders.
32 * the data to put into the placeholders: ${var}, $!{var},
35 public SprintfCommand(String text, List<String> store) {
37 this.store = store.toArray(new String[store.size()]);
40 private static final String VARIABLE = "\\$!?\\{[a-zA-Z0-9_-]+\\}";
42 private static final Pattern processingInstruction = Pattern.compile("(" + VARIABLE + ")|(?:(!'[^{}'\\$]*)')|(?:(!\\([^{})\\$]*)\\))");
45 * Creates a new SprintfCommand that is parsed as from template source.
48 * the part from the template that is to be parsed.
50 protected SprintfCommand(String content) {
51 StringBuffer raw = new StringBuffer();
52 List<String> var = new LinkedList<String>();
54 Matcher m = processingInstruction.matcher(content);
57 raw.append(content.substring(last, m.start()));
59 if ((group = m.group(1)) != null) {
61 } else if ((group = m.group(2)) != null) {
63 } else if ((group = m.group(3)) != null) {
66 throw new Error("Regex is broken??");
69 raw.append("{" + (counter++) + "}");
71 raw.append(content.substring(last));
72 text = raw.toString();
73 store = var.toArray(new String[var.size()]);
76 private static final Pattern replacant = Pattern.compile("\\{([0-9]+)\\}");
79 public void output(PrintWriter out, Language l, Map<String, Object> vars) {
80 String parts = l.getTranslation(text);
81 Matcher m = replacant.matcher(parts);
84 out.print(escape(vars, parts.substring(pos, m.start())));
85 String var = store[Integer.parseInt(m.group(1))];
86 if (var.startsWith("$!")) {
87 Template.outputVar(out, l, vars, var.substring(3, var.length() - 1), true);
88 } else if (var.startsWith("!'")) {
89 out.print(var.substring(2));
90 } else if (var.startsWith("!(")) {
91 String host = (String) vars.get(Gigi.LINK_HOST);
93 throw new Error("Unconfigured link-host while interpreting link-syntax.");
95 if (var.charAt(2) != '/') {
96 throw new Error("Need an absolute link for the link service.");
98 String link = "//" + host + var.substring(2);
99 out.print("<a href='" + HTMLEncoder.encodeHTML(link) + "'>");
100 } else if (var.startsWith("$")) {
101 Template.outputVar(out, l, vars, var.substring(2, var.length() - 1), false);
103 throw new Error("Processing error in template.");
108 out.print(escape(vars, parts.substring(pos)));
111 private String escape(Map<String, Object> vars, String target) {
112 if (vars.containsKey(OUT_KEY_PLAIN)) {
115 return HTMLEncoder.encodeHTML(target);
119 public void addTranslations(Collection<String> s) {
124 * Creates a simple {@link SprintfCommand} wrapped in a {@link Scope} to fit
125 * in now constant variables into this template.
128 * the message (to be translated) with <code>{0},{1},...</code>
131 * the variables to put into the placeholders.
132 * @return the constructed {@link Outputable}.
134 public static Outputable createSimple(String msg, Object... vars) {
135 HashMap<String, Object> scope = new HashMap<>();
136 String[] store = new String[vars.length];
137 for (int i = 0; i < vars.length; i++) {
138 scope.put("autoVar" + i, vars[i]);
139 store[i] = "${autoVar" + i + "}";
141 return new Scope(new SprintfCommand(msg, Arrays.asList(store)), scope);