X-Git-Url: https://code.wpia.club/?p=gigi.git;a=blobdiff_plain;f=src%2Forg%2Fcacert%2Fgigi%2Foutput%2Ftemplate%2FTemplate.java;fp=src%2Forg%2Fcacert%2Fgigi%2Foutput%2Ftemplate%2FTemplate.java;h=0000000000000000000000000000000000000000;hp=6aa9348a7f1ed942a782b3af59144fc0240e2e29;hb=bccd4cc0dba0f89aa045b113bac46eb8cc1dab4e;hpb=c9ed09f0007fc2c813815be927a5a24b23dab83c diff --git a/src/org/cacert/gigi/output/template/Template.java b/src/org/cacert/gigi/output/template/Template.java deleted file mode 100644 index 6aa9348a..00000000 --- a/src/org/cacert/gigi/output/template/Template.java +++ /dev/null @@ -1,359 +0,0 @@ -package org.cacert.gigi.output.template; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintWriter; -import java.io.Reader; -import java.net.URISyntaxException; -import java.net.URL; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Collection; -import java.util.Date; -import java.util.LinkedList; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.cacert.gigi.localisation.Language; -import org.cacert.gigi.output.DateSelector; -import org.cacert.gigi.util.DayDate; -import org.cacert.gigi.util.EditDistance; -import org.cacert.gigi.util.HTMLEncoder; - -/** - * Represents a loaded template file. - */ -public class Template implements Outputable { - - protected static class ParseResult { - - TemplateBlock block; - - String endType; - - public ParseResult(TemplateBlock block, String endType) { - this.block = block; - this.endType = endType; - } - - public String getEndType() { - return endType; - } - - public TemplateBlock getBlock(String reqType) { - if (endType == null && reqType == null) { - return block; - } - if (endType == null || reqType == null) { - throw new Error("Invalid block type: " + endType); - } - if (endType.equals(reqType)) { - return block; - } - throw new Error("Invalid block type: " + endType); - } - } - - private TemplateBlock data; - - private long lastLoaded; - - private File source; - - private static final Pattern CONTROL_PATTERN = Pattern.compile(" ?([a-zA-Z]+)\\(\\$([^)]+)\\) ?\\{ ?"); - - private static final Pattern ELSE_PATTERN = Pattern.compile(" ?\\} ?else ?\\{ ?"); - - private static final String[] POSSIBLE_CONTROL_PATTERNS = new String[] { - "if", "else", "foreach" - }; - - private static final String UNKOWN_CONTROL_STRUCTURE_MSG = "Unknown control structure \"%s\", did you mean \"%s\"?"; - - /** - * Creates a new template by parsing the contents from the given URL. This - * constructor will fail on syntax error. When the URL points to a file, - * {@link File#lastModified()} is monitored for changes of the template. - * - * @param u - * the URL to load the template from. UTF-8 is chosen as charset. - */ - public Template(URL u) { - try (Reader r = new InputStreamReader(u.openStream(), "UTF-8")) { - try { - if (u.getProtocol().equals("file")) { - source = new File(u.toURI()); - lastLoaded = source.lastModified() + 1000; - } - } catch (URISyntaxException e) { - e.printStackTrace(); - } - data = parse(r).getBlock(null); - } catch (IOException e) { - throw new Error(e); - } - } - - /** - * Creates a new template by parsing the contents from the given reader. - * This constructor will fail on syntax error. - * - * @param r - * the Reader containing the data. - */ - public Template(Reader r) { - try { - data = parse(r).getBlock(null); - r.close(); - } catch (IOException e) { - throw new Error(e); - } - } - - protected ParseResult parse(Reader r) throws IOException { - return parseContent(r); - } - - protected ParseResult parseContent(Reader r) throws IOException { - ParseContext context = new ParseContext(r); - ParseResult result = parseContent(context); - if (context.parseException.isEmpty()) { - return result; - } - while (context.curChar != -1) { - parseContent(context); - } - throw context.parseException; - } - - protected ParseResult parseContent(ParseContext context) throws IOException { - LinkedList splitted = new LinkedList(); - LinkedList commands = new LinkedList(); - StringBuffer buf = new StringBuffer(); - String blockType = null; - ParseContext tContext = null; - outer: - while (true) { - if (tContext != null) { - context.merge(tContext); - } - while ( !endsWith(buf, "")) { - int ch = context.read(); - if (ch == -1) { - context.addError("Expected \"?>\""); - return null; - } - buf.append((char) ch); - } - buf.delete(buf.length() - 2, buf.length()); - String com = buf.toString().replace("\n", ""); - buf.delete(0, buf.length()); - Matcher m = CONTROL_PATTERN.matcher(com); - if (m.matches()) { - String type = m.group(1); - String variable = m.group(2); - ParseContext bodyContext = tContext.copy(); - ParseResult body = parseContent(bodyContext); - if (type.equals("if")) { - if ("else".equals(body.getEndType())) { - ParseContext bodyContext2 = bodyContext.copy(); - commands.add(new IfStatement(variable, body.getBlock("else"), parseContent(bodyContext).getBlock("}"))); - bodyContext.merge(bodyContext2); - } else { - commands.add(new IfStatement(variable, body.getBlock("}"))); - } - } else if (type.equals("foreach")) { - commands.add(new ForeachStatement(variable, body.getBlock("}"))); - } else { - String bestMatching = EditDistance.getBestMatchingStringByEditDistance(type, POSSIBLE_CONTROL_PATTERNS); - tContext.addError(String.format(UNKOWN_CONTROL_STRUCTURE_MSG, type, bestMatching)); - } - tContext.merge(bodyContext); - continue; - } else if ((m = ELSE_PATTERN.matcher(com)).matches()) { - blockType = "else"; - break; - } else if (com.matches(" ?\\} ?")) { - blockType = "}"; - break; - } else { - commands.add(parseCommand(com, tContext)); - } - } - if (tContext != null) { - context.merge(tContext); - } - splitted.add(buf.toString()); - ParseResult result = new ParseResult(new TemplateBlock(splitted.toArray(new String[splitted.size()]), commands.toArray(new Translatable[commands.size()])), blockType); - return result; - } - - private boolean endsWith(StringBuffer buf, String string) { - return buf.length() >= string.length() && buf.substring(buf.length() - string.length(), buf.length()).equals(string); - } - - private Translatable parseCommand(String s2, ParseContext context) { - if (s2.startsWith("=_")) { - final String raw = s2.substring(2); - if ( !s2.contains("$") && !s2.contains("!'")) { - return new TranslateCommand(raw); - } else { - return new SprintfCommand(raw); - } - } else if (s2.startsWith("=$")) { - final String raw = s2.substring(2); - return new OutputVariableCommand(raw); - } else { - context.addError("Unknown processing instruction \"" + s2 + "\"," + " did you mean \"" + EditDistance.getBestMatchingStringByEditDistance(s2, new String[] { - "=_", "=$" - }) + "\"?"); - return null; - } - } - - @Override - public void output(PrintWriter out, Language l, Map vars) { - tryReload(); - data.output(out, l, vars); - } - - protected void tryReload() { - if (source != null && lastLoaded < source.lastModified()) { - System.out.println("Reloading template.... " + source); - try (InputStreamReader r = new InputStreamReader(new FileInputStream(source), "UTF-8")) { - data = parse(r).getBlock(null); - r.close(); - lastLoaded = source.lastModified() + 1000; - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - protected static void outputVar(PrintWriter out, Language l, Map vars, String varname, boolean unescaped) { - if (vars.containsKey(Outputable.OUT_KEY_PLAIN)) { - unescaped = true; - } - Object s = vars.get(varname); - - if (s == null) { - System.err.println("Empty variable: " + varname); - } - if (s instanceof Outputable) { - ((Outputable) s).output(out, l, vars); - } else if (s instanceof DayDate) { - out.print(DateSelector.getDateFormat().format(((DayDate) s).toDate())); - } else if (s instanceof Boolean) { - out.print(((Boolean) s) ? l.getTranslation("yes") : l.getTranslation("no")); - } else if (s instanceof Date) { - SimpleDateFormat sdfUI = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); - out.print(""); - } else { - out.print(s == null ? "null" : (unescaped ? s.toString() : HTMLEncoder.encodeHTML(s.toString()))); - } - } - - public void addTranslations(Collection s) { - data.addTranslations(s); - } - - private class ParseContext { - - public static final int CONTEXT_LENGTH = 20; - - private Reader reader; - - public final TemplateParseException parseException = new TemplateParseException(source); - - int line = 1; - - int column = 0; - - private int curChar = -1; - - private int[] charContext = new int[CONTEXT_LENGTH]; - - protected int contextPosition = 0; - - public ParseContext(Reader reader) { - this.reader = reader; - } - - public void addError(String message) { - addError(line, column, message); - } - - public void addError(int line, int column, String message) { - StringBuffer charContextBuffer = new StringBuffer(); - int j = contextPosition; - for (int i = 0; i < CONTEXT_LENGTH; i++) { - if (charContext[j] != 0) { - if (charContext[j] == '\n') { - charContextBuffer.append("\\n"); - } else { - charContextBuffer.appendCodePoint(charContext[j]); - } - } - j = (j + 1) % CONTEXT_LENGTH; - } - parseException.addError(line, column, message, charContextBuffer.toString()); - } - - public void merge(ParseContext other) { - line = other.line; - column = other.column; - parseException.append(other.parseException); - } - - public void append(ParseContext other) { - parseException.append(other.parseException); - } - - public int read() throws IOException { - int ch; - while ((ch = reader.read()) == '\r') { - } - curChar = ch; - if (ch == '\n') { - line++; - column = 0; - } else { - column++; - } - if (ch != -1) { - charContext[contextPosition] = ch; - contextPosition = (contextPosition + 1) % CONTEXT_LENGTH; - } - return ch; - } - - public ParseContext copy() { - ParseContext newParseContext = new ParseContext(reader); - newParseContext.line = line; - newParseContext.column = column; - newParseContext.charContext = Arrays.copyOf(charContext, charContext.length); - newParseContext.contextPosition = contextPosition; - return newParseContext; - } - } -}