From d1c0a9beb44bd6904475e593a9e7d60a0f0c98bc Mon Sep 17 00:00:00 2001 From: =?utf8?q?Felix=20D=C3=B6rre?= Date: Sat, 18 Feb 2017 01:39:57 +0100 Subject: [PATCH] upd: document variables in SprintfCommand more clearly Change-Id: I4227c3f38cf811c5efddf0e5ff31775df16fe861 --- .../gigi/output/template/SprintfCommand.java | 112 +++++++++++------- src/club/wpia/gigi/pages/Verify.java | 4 +- .../wpia/gigi/util/AuthorizationContext.java | 4 +- 3 files changed, 70 insertions(+), 50 deletions(-) diff --git a/src/club/wpia/gigi/output/template/SprintfCommand.java b/src/club/wpia/gigi/output/template/SprintfCommand.java index 015fe6b6..d313df8a 100644 --- a/src/club/wpia/gigi/output/template/SprintfCommand.java +++ b/src/club/wpia/gigi/output/template/SprintfCommand.java @@ -19,93 +19,113 @@ import club.wpia.gigi.util.HTMLEncoder; */ public final class SprintfCommand implements Translatable { - private final String text; + /** + * The pattern to fill. Containing placeholders of pattern + * {@link #placeholder}. This is the string that will be translated. + */ + private final String pattern; - private final String[] store; + /** + * A regex that matches the replacement patterns like "{0}" or "{1}". + */ + private static final Pattern placeholder = Pattern.compile("\\{([0-9]+)\\}"); + + /** + * The values describing what to put into the {@link #placeholder}s of + * {@link #pattern}. + */ + private final String[] replacements; /** - * Creates a new SprintfCommand based on its pre-parsed contents. + * Regex for detecting processing instructions in a in-template + * SprintfCommand. + */ + private static final Pattern processingInstruction = Pattern.compile("(?:(\\$!?\\{[a-zA-Z0-9_-]+)\\})|(?:(!'[^{}'\\$]*)')|(?:(!\\([^{})\\$]*)\\))"); + + /** + * Creates a new SprintfCommand based on its pre-parsed contents. This is + * the variant that the data is stored internally in this class. So the + * pattern has numbers as placeholders and the replacement list + * contains the instructions on what to put in there (without closing + * brackets, etc.). * - * @param text + * @param pattern * a string with {0},{1},.. as placeholders. - * @param store - * the data to put into the placeholders: ${var}, $!{var}, - * !'plain', !(/link). + * @param replacements + * instructions for what data to put into the placeholders: + * ${var, $!{var, !'plain, + * !(/link. */ - public SprintfCommand(String text, List store) { - this.text = text; - this.store = store.toArray(new String[store.size()]); + public SprintfCommand(String pattern, List replacements) { + this.pattern = pattern; + this.replacements = replacements.toArray(new String[replacements.size()]); } - private static final String VARIABLE = "\\$!?\\{[a-zA-Z0-9_-]+\\}"; - - private static final Pattern processingInstruction = Pattern.compile("(" + VARIABLE + ")|(?:(!'[^{}'\\$]*)')|(?:(!\\([^{})\\$]*)\\))"); - /** - * Creates a new SprintfCommand that is parsed as from template source. + * Creates a new SprintfCommand that is parsed as from template source. This + * version is internally used to create {@link SprintfCommand}s from the + * literals specified in {@link Template}s. * * @param content * the part from the template that is to be parsed. */ protected SprintfCommand(String content) { - StringBuffer raw = new StringBuffer(); - List var = new LinkedList(); + StringBuffer pattern = new StringBuffer(); + List replacements = new LinkedList(); int counter = 0; Matcher m = processingInstruction.matcher(content); int last = 0; while (m.find()) { - raw.append(content.substring(last, m.start())); + pattern.append(content.substring(last, m.start())); String group = null; if ((group = m.group(1)) != null) { - var.add(group); + replacements.add(group); } else if ((group = m.group(2)) != null) { - var.add(group); + replacements.add(group); } else if ((group = m.group(3)) != null) { - var.add(group); + replacements.add(group); } else { throw new Error("Regex is broken??"); } last = m.end(); - raw.append("{" + (counter++) + "}"); + pattern.append("{" + (counter++) + "}"); } - raw.append(content.substring(last)); - text = raw.toString(); - store = var.toArray(new String[var.size()]); + pattern.append(content.substring(last)); + this.pattern = pattern.toString(); + this.replacements = replacements.toArray(new String[replacements.size()]); } - private static final Pattern replacant = Pattern.compile("\\{([0-9]+)\\}"); - @Override - public void output(PrintWriter out, Language l, Map vars) { - String parts = l.getTranslation(text); - Matcher m = replacant.matcher(parts); + public void output(PrintWriter out, Language l, Map externalVariables) { + String parts = l.getTranslation(pattern); + Matcher m = placeholder.matcher(parts); int pos = 0; while (m.find()) { - out.print(escape(vars, parts.substring(pos, m.start()))); - String var = store[Integer.parseInt(m.group(1))]; - if (var.startsWith("$!")) { - Template.outputVar(out, l, vars, var.substring(3, var.length() - 1), true); - } else if (var.startsWith("!'")) { - out.print(var.substring(2)); - } else if (var.startsWith("!(")) { - String host = (String) vars.get(Gigi.LINK_HOST); + out.print(escape(externalVariables, parts.substring(pos, m.start()))); + String replacement = replacements[Integer.parseInt(m.group(1))]; + if (replacement.startsWith("$!")) { + Template.outputVar(out, l, externalVariables, replacement.substring(3), true); + } else if (replacement.startsWith("!'")) { + out.print(replacement.substring(2)); + } else if (replacement.startsWith("!(")) { + String host = (String) externalVariables.get(Gigi.LINK_HOST); if (host == null) { throw new Error("Unconfigured link-host while interpreting link-syntax."); } - if (var.charAt(2) != '/') { + if (replacement.charAt(2) != '/') { throw new Error("Need an absolute link for the link service."); } - String link = "//" + host + var.substring(2); + String link = "//" + host + replacement.substring(2); out.print(""); - } else if (var.startsWith("$")) { - Template.outputVar(out, l, vars, var.substring(2, var.length() - 1), false); + } else if (replacement.startsWith("$")) { + Template.outputVar(out, l, externalVariables, replacement.substring(2), false); } else { throw new Error("Processing error in template."); } pos = m.end(); } - out.print(escape(vars, parts.substring(pos))); + out.print(escape(externalVariables, parts.substring(pos))); } private String escape(Map vars, String target) { @@ -117,7 +137,7 @@ public final class SprintfCommand implements Translatable { @Override public void addTranslations(Collection s) { - s.add(text); + s.add(pattern); } /** @@ -128,7 +148,7 @@ public final class SprintfCommand implements Translatable { * the message (to be translated) with {0},{1},... * as placeholders. * @param vars - * the variables to put into the placeholders. + * the contents of the variables to put into the placeholders. * @return the constructed {@link Outputable}. */ public static Outputable createSimple(String msg, Object... vars) { @@ -136,7 +156,7 @@ public final class SprintfCommand implements Translatable { String[] store = new String[vars.length]; for (int i = 0; i < vars.length; i++) { scope.put("autoVar" + i, vars[i]); - store[i] = "${autoVar" + i + "}"; + store[i] = "${autoVar" + i; } return new Scope(new SprintfCommand(msg, Arrays.asList(store)), scope); } diff --git a/src/club/wpia/gigi/pages/Verify.java b/src/club/wpia/gigi/pages/Verify.java index 930b5efb..da43ab92 100644 --- a/src/club/wpia/gigi/pages/Verify.java +++ b/src/club/wpia/gigi/pages/Verify.java @@ -20,9 +20,9 @@ import club.wpia.gigi.output.template.SprintfCommand; public class Verify extends Page { - private static final SprintfCommand emailAddressVerified = new SprintfCommand("Email address {0} verified", Arrays.asList("${subject}")); + private static final SprintfCommand emailAddressVerified = new SprintfCommand("Email address {0} verified", Arrays.asList("${subject")); - private static final SprintfCommand domainVerified = new SprintfCommand("Domain {0} verified", Arrays.asList("${subject}")); + private static final SprintfCommand domainVerified = new SprintfCommand("Domain {0} verified", Arrays.asList("${subject")); private class VerificationForm extends Form { diff --git a/src/club/wpia/gigi/util/AuthorizationContext.java b/src/club/wpia/gigi/util/AuthorizationContext.java index fdc9187b..84f10f74 100644 --- a/src/club/wpia/gigi/util/AuthorizationContext.java +++ b/src/club/wpia/gigi/util/AuthorizationContext.java @@ -65,9 +65,9 @@ public class AuthorizationContext implements Outputable, Serializable { return getSupporterTicketId() != null && isInGroup(Group.SUPPORTER); } - private static final SprintfCommand sp = new SprintfCommand("Logged in as {0} via {1}.", Arrays.asList("${username}", "${loginMethod}")); + private static final SprintfCommand sp = new SprintfCommand("Logged in as {0} via {1}.", Arrays.asList("${username", "${loginMethod")); - private static final SprintfCommand inner = new SprintfCommand("{0} (on behalf of {1})", Arrays.asList("${user}", "${target}")); + private static final SprintfCommand inner = new SprintfCommand("{0} (on behalf of {1})", Arrays.asList("${user", "${target")); @Override public void output(PrintWriter out, Language l, Map vars) { -- 2.39.2