root/livinglogic.java.ul4/src/main/java/com/livinglogic/ul4/InterpretedTemplate.java @ 920:6090c7799c51

Revision 920:6090c7799c51, 28.6 KB (checked in by Walter Doerwald <walter@…>, 5 years ago)

Implement if expressions.

Line 
1/*
2** Copyright 2009-2013 by LivingLogic AG, Bayreuth/Germany
3** All Rights Reserved
4** See LICENSE for the license
5*/
6
7package com.livinglogic.ul4;
8
9import static com.livinglogic.utils.SetUtils.makeExtendedSet;
10
11import java.io.IOException;
12import java.io.PipedReader;
13import java.io.PipedWriter;
14import java.io.Reader;
15import java.io.StringWriter;
16import java.io.Writer;
17import java.util.LinkedList;
18import java.util.List;
19import java.util.Map;
20import java.util.Set;
21import java.util.Stack;
22import java.util.regex.Matcher;
23import java.util.regex.Pattern;
24
25import org.antlr.runtime.ANTLRStringStream;
26import org.antlr.runtime.CommonTokenStream;
27import org.antlr.runtime.RecognitionException;
28
29import com.livinglogic.ul4on.Decoder;
30import com.livinglogic.ul4on.Encoder;
31import com.livinglogic.ul4on.ObjectFactory;
32import com.livinglogic.ul4on.UL4ONSerializable;
33import com.livinglogic.ul4on.Utils;
34
35
36public class InterpretedTemplate extends Block implements UL4Name, UL4CallWithContext, UL4Type, UL4Attributes
37{
38    /**
39     * The version number used in the UL4ON dump of the template.
40     */
41    public static final String VERSION = "26";
42
43    /**
44     * The name of the template/function (defaults to {@code null})
45     */
46    public String name = null;
47
48    /**
49     * Should whitespace be skipped when outputting text nodes?
50     * (i.e. linefeed and the whitespace after the linefeed will be skipped. Other spaces/tabs etc. will not be skipped)
51     */
52    public boolean keepWhitespace = true;
53
54    /**
55     * The start delimiter for tags (defaults to {@code "<?"})
56     */
57    public String startdelim = "<?";
58
59    /**
60     * The end delimiter for tags (defaults to {@code "?>"})
61     */
62    public String enddelim = "?>";
63
64    /**
65     * The template/function source (of the top-level template, i.e. subtemplates always get the full source).
66     */
67    public String source = null;
68
69    public InterpretedTemplate(String source) throws RecognitionException
70    {
71        this(source, null, true, "<?", "?>");
72    }
73
74    public InterpretedTemplate(String source, boolean keepWhitespace) throws RecognitionException
75    {
76        this(source, null, keepWhitespace, "<?", "?>");
77    }
78
79    public InterpretedTemplate(String source, String name) throws RecognitionException
80    {
81        this(source, name, true, "<?", "?>");
82    }
83
84    public InterpretedTemplate(String source, String name, boolean keepWhitespace) throws RecognitionException
85    {
86        this(source, name, keepWhitespace, "<?", "?>");
87    }
88
89    public InterpretedTemplate(String source, String startdelim, String enddelim) throws RecognitionException
90    {
91        this(source, null, true, startdelim, enddelim);
92    }
93
94    public InterpretedTemplate(String source, boolean keepWhitespace, String startdelim, String enddelim) throws RecognitionException
95    {
96        this(source, null, keepWhitespace, startdelim, enddelim);
97    }
98
99    public InterpretedTemplate(String source, String name, boolean keepWhitespace, String startdelim, String enddelim) throws RecognitionException
100    {
101        this(null, source, name, keepWhitespace, startdelim, enddelim);
102        compile();
103    }
104
105    /**
106     * Creates an {@code InterpretedTemplate} object. The content will be filled later through a call to {@link #compile)
107     */
108    public InterpretedTemplate(Location location, String source, String name, boolean keepWhitespace, String startdelim, String enddelim)
109    {
110        super(location, 0, 0);
111        this.source = source;
112        this.name = name;
113        this.keepWhitespace = keepWhitespace;
114        this.startdelim = startdelim;
115        this.enddelim = enddelim;
116    }
117
118    protected void compile() throws RecognitionException
119    {
120        if (source == null)
121            return;
122
123        List<Location> tags = tokenizeTags(source, startdelim, enddelim);
124
125        // Stack of currently active blocks
126        Stack<Block> stack = new Stack<Block>();
127        stack.push(this);
128
129        for (Location location : tags)
130        {
131            try
132            {
133                Block innerBlock = stack.peek();
134                String type = location.getType();
135                // FIXME: use a switch in Java 7
136                if (type == null)
137                {
138                    innerBlock.append(new Text(location, location.getStartCode(), location.getEndCode()));
139                }
140                else if (type.equals("print"))
141                {
142                    UL4Parser parser = getParser(location);
143                    innerBlock.append(new Print(location, location.getStartCode(), location.getEndCode(), parser.expression()));
144                }
145                else if (type.equals("printx"))
146                {
147                    UL4Parser parser = getParser(location);
148                    innerBlock.append(new PrintX(location, location.getStartCode(), location.getEndCode(), parser.expression()));
149                }
150                else if (type.equals("code"))
151                {
152                    UL4Parser parser = getParser(location);
153                    innerBlock.append(parser.stmt());
154                }
155                else if (type.equals("if"))
156                {
157                    UL4Parser parser = getParser(location);
158                    ConditionalBlockBlock node = new ConditionalBlockBlock(location, location.getStartCode(), location.getEndCode(), new If(location, location.getStartCode(), location.getEndCode(), parser.expression()));
159                    innerBlock.append(node);
160                    stack.push(node);
161                }
162                else if (type.equals("elif"))
163                {
164                    if (innerBlock instanceof ConditionalBlockBlock)
165                    {
166                        UL4Parser parser = getParser(location);
167                        ((ConditionalBlockBlock)innerBlock).startNewBlock(new ElIf(location, location.getStartCode(), location.getEndCode(), parser.expression()));
168                    }
169                    else
170                        throw new BlockException("elif doesn't match any if");
171                }
172                else if (type.equals("else"))
173                {
174                    if (innerBlock instanceof ConditionalBlockBlock)
175                    {
176                        ((ConditionalBlockBlock)innerBlock).startNewBlock(new Else(location, location.getStartCode(), location.getEndCode()));
177                    }
178                    else
179                        throw new BlockException("else doesn't match any if");
180                }
181                else if (type.equals("end"))
182                {
183                    if (stack.size() > 1)
184                    {
185                        innerBlock.finish(location);
186                        stack.pop();
187                    }
188                    else
189                        throw new BlockException("not in any block");
190                }
191                else if (type.equals("for"))
192                {
193                    UL4Parser parser = getParser(location);
194                    Block node = parser.for_();
195                    innerBlock.append(node);
196                    stack.push(node);
197                }
198                else if (type.equals("break"))
199                {
200                    for (int i = stack.size()-1; i >= 0; --i)
201                    {
202                        if (stack.get(i).handleLoopControl("break"))
203                            break;
204                    }
205                    innerBlock.append(new Break(location, location.getStartCode(), location.getEndCode()));
206                }
207                else if (type.equals("continue"))
208                {
209                    for (int i = stack.size()-1; i >= 0; --i)
210                    {
211                        if (stack.get(i).handleLoopControl("continue"))
212                            break;
213                    }
214                    innerBlock.append(new Continue(location, location.getStartCode(), location.getEndCode()));
215                }
216                else if (type.equals("return"))
217                {
218                    UL4Parser parser = getParser(location);
219                    innerBlock.append(new Return(location, location.getStartCode(), location.getEndCode(), parser.expression()));
220                }
221                else if (type.equals("def"))
222                {
223                    // Copy over all the attributes, however passing a {@link Location} will prevent compilation
224                    InterpretedTemplate subtemplate = new InterpretedTemplate(location, source, location.getCode(), keepWhitespace, startdelim, enddelim);
225                    innerBlock.append(subtemplate);
226                    stack.push(subtemplate);
227                }
228                else
229                {
230                    // Can't happen
231                    throw new RuntimeException("unknown tag " + type);
232                }
233            }
234            catch (Exception ex)
235            {
236                throw new TemplateException(new LocationException(ex, location), this);
237            }
238        }
239        if (stack.size() > 1) // the template itself is still on the stack
240        {
241            Block innerBlock = stack.peek();
242            throw new ASTException(new BlockException(innerBlock.getType() + " block unclosed"), innerBlock);
243        }
244    }
245
246    private UL4Parser getParser(Location location)
247    {
248        return getParser(location, location.getCode());
249    }
250
251    private UL4Parser getParser(Location location, String source)
252    {
253        ANTLRStringStream input = new ANTLRStringStream(source);
254        UL4Lexer lexer = new UL4Lexer(location, input);
255        CommonTokenStream tokens = new CommonTokenStream(lexer);
256        UL4Parser parser = new UL4Parser(location, tokens);
257        return parser;
258    }
259
260    public String nameUL4()
261    {
262        return name;
263    }
264
265    public void setName(String name)
266    {
267        this.name = name;
268    }
269
270    public String getSource()
271    {
272        return source;
273    }
274
275    public boolean getKeepWhitespace()
276    {
277        return keepWhitespace;
278    }
279
280    public String getStartDelim()
281    {
282        return startdelim;
283    }
284
285    public String getEndDelim()
286    {
287        return enddelim;
288    }
289
290    public void toString(Formatter formatter)
291    {
292        formatter.write("def ");
293        formatter.write(name != null ? name : "unnamed");
294        formatter.write(":");
295        formatter.lf();
296        formatter.indent();
297        super.toString(formatter);
298        formatter.dedent();
299    }
300
301    /**
302     * loads a template from a string in the UL4ON serialization format.
303     * @param data The template in serialized form.
304     * @return The template object.
305     */
306    public static InterpretedTemplate loads(String data)
307    {
308        return (InterpretedTemplate)Utils.loads(data);
309    }
310
311    /**
312     * loads a template from a reader in the UL4ON serialization format.
313     * @param reader The Reader object from which to read the template.
314     * @return The template object.
315     * @throws IOException if reading from the stream fails
316     */
317    public static InterpretedTemplate load(Reader reader) throws IOException
318    {
319        return (InterpretedTemplate)Utils.load(reader);
320    }
321
322    /**
323     * writes the {@code InterpretedTemplate} object to a string in the UL4ON serialization format.
324     * @return The string containing the template/function in serialized form.
325     */
326    public String dumps()
327    {
328        return Utils.dumps(this);
329    }
330
331    /**
332     * Renders the template.
333     * @param context   the EvaluationContext.
334     */
335    public void render(EvaluationContext context)
336    {
337        InterpretedTemplate oldTemplate = context.setTemplate(this);
338        try
339        {
340            super.evaluate(context);
341        }
342        catch (BreakException ex)
343        {
344            throw ex;
345        }
346        catch (ContinueException ex)
347        {
348            throw ex;
349        }
350        catch (ReturnException ex)
351        {
352            // ignore return value and end rendering
353        }
354        catch (Exception ex)
355        {
356            throw new TemplateException(ex, this);
357        }
358        finally
359        {
360            context.setTemplate(oldTemplate);
361        }
362    }
363
364    /**
365     * Renders the template using the passed in variables.
366     * @param variables a map containing the top level variables that should be
367     *                  available to the template code. May be null.
368     */
369    public void render(EvaluationContext context, Map<String, Object> variables)
370    {
371        Map<String, Object> oldVariables = context.setVariables(variables);
372        try
373        {
374            render(context);
375        }
376        finally
377        {
378            context.setVariables(oldVariables);
379        }
380    }
381
382    /**
383     * Renders the template to a java.io.Writer object.
384     * @param writer    the java.io.Writer object to which the output is written.
385     * @param variables a map containing the top level variables that should be
386     *                  available to the template code. May be null.
387     */
388    public void render(java.io.Writer writer, Map<String, Object> variables)
389    {
390        EvaluationContext context = new EvaluationContext(writer, variables);
391        try
392        {
393            render(context);
394        }
395        finally
396        {
397            context.close();
398        }
399    }
400
401    /**
402     * Renders the template and returns the resulting string.
403     * @return The render output as a string.
404     */
405    public String renders()
406    {
407        EvaluationContext context = new EvaluationContext(null, null);
408        try
409        {
410            return renders(context);
411        }
412        finally
413        {
414            context.close();
415        }
416    }
417
418    /**
419     * Renders the template and returns the resulting string.
420     * @return The render output as a string.
421     */
422    public String renders(EvaluationContext context)
423    {
424        StringWriter output = new StringWriter();
425        Writer oldWriter = context.setWriter(output);
426        try
427        {
428            render(context);
429        }
430        finally
431        {
432            context.setWriter(oldWriter);
433        }
434        return output.toString();
435    }
436
437    /**
438     * Renders the template using the passed in variables and returns the resulting string.
439     * @param variables a map containing the top level variables that should be
440     *                  available to the template code. May be null
441     * @return The render output as a string.
442     */
443    public String renders(EvaluationContext context, Map<String, Object> variables)
444    {
445        Map<String, Object> oldVariables = context.setVariables(variables);
446        try
447        {
448            return renders(context);
449        }
450        finally
451        {
452            context.setVariables(oldVariables);
453        }
454    }
455
456    /**
457     * Renders the template and returns the resulting string.
458     * @param variables a map containing the top level variables that should be
459     *                  available to the template code. May be null
460     * @return The render output as a string.
461     */
462    public String renders(Map<String, Object> variables)
463    {
464        StringWriter output = new StringWriter();
465        render(output, variables);
466        return output.toString();
467    }
468
469    private static class RenderRunnable implements Runnable
470    {
471        protected InterpretedTemplate template;
472        protected Writer writer;
473        protected Map<String, Object> variables;
474
475        public RenderRunnable(InterpretedTemplate template, Writer writer, Map<String, Object> variables)
476        {
477            this.template = template;
478            this.writer = writer;
479            this.variables = variables;
480        }
481
482        @Override
483        public void run()
484        {
485            template.render(writer, variables);
486            try
487            {
488                writer.close();
489            }
490            catch (IOException exc)
491            {
492                throw new RuntimeException(exc);
493            }
494        }
495    }
496
497    /**
498     * Renders the template and returns a Reader object from which the template
499     * output can be read.
500     * @param variables a map containing the top level variables that should be
501     *                  available to the template code. May be null
502     * @return The reader from which the template output can be read.
503     * @throws IOException
504     */
505    public Reader reader(Map<String, Object> variables) throws IOException
506    {
507        PipedReader reader = new PipedReader(10);
508        PipedWriter writer = new PipedWriter(reader);
509        new Thread(new RenderRunnable(this, writer, variables)).start();
510        return reader;
511    }
512
513    public Object callUL4(EvaluationContext context, Object[] args, Map<String, Object> kwargs)
514    {
515        if (args.length > 0)
516            throw new PositionalArgumentsNotSupportedException(name);
517        return call(context, kwargs);
518    }
519
520    /**
521     * Executes the function.
522     * @param context   the EvaluationContext.
523     * @return the return value of the function
524     */
525    public Object call(EvaluationContext context)
526    {
527        InterpretedTemplate oldTemplate = context.setTemplate(this);
528        try
529        {
530            super.evaluate(context);
531            return null;
532        }
533        catch (BreakException ex)
534        {
535            throw ex;
536        }
537        catch (ContinueException ex)
538        {
539            throw ex;
540        }
541        catch (ReturnException ex)
542        {
543            return ex.getValue();
544        }
545        catch (Exception ex)
546        {
547            throw new TemplateException(ex, this);
548        }
549        finally
550        {
551            context.setTemplate(oldTemplate);
552        }
553    }
554
555    /**
556     * Executes the function using the passed in variables.
557     * @param variables a map containing the top level variables that should be
558     *                  available to the function code. May be null.
559     * @return the return value of the function
560     */
561    public Object call(EvaluationContext context, Map<String, Object> variables)
562    {
563        Map<String, Object> oldVariables = context.setVariables(variables);
564        try
565        {
566            return call(context);
567        }
568        finally
569        {
570            context.setVariables(oldVariables);
571        }
572    }
573
574    /**
575     * Executes the function.
576     * @param variables a map containing the top level variables that should be
577     *                  available to the function code. May be null.
578     * @return the return value of the function
579     */
580    public Object call(Map<String, Object> variables)
581    {
582        EvaluationContext context = new EvaluationContext(null, variables);
583        try
584        {
585            return call(context);
586        }
587        finally
588        {
589            context.close();
590        }
591    }
592
593    public Object evaluate(EvaluationContext context)
594    {
595        context.set(name, new TemplateClosure(this, context.getVariables()));
596        return null;
597    }
598
599    public String getType()
600    {
601        return "template";
602    }
603
604    public String typeUL4()
605    {
606        return "template";
607    }
608
609    private static String removeWhitespace(String string)
610    {
611        StringBuilder buffer = new StringBuilder();
612        boolean keepWS = true;
613
614        for (int i = 0; i < string.length(); ++i)
615        {
616            char c = string.charAt(i);
617
618            if (c == '\n')
619                keepWS = false;
620            else if (Character.isWhitespace(c))
621            {
622                if (keepWS)
623                    buffer.append(c);
624            }
625            else
626            {
627                buffer.append(c);
628                keepWS = true;
629            }
630        }
631
632        return buffer.toString();
633    }
634
635    public String formatText(String text)
636    {
637        return keepWhitespace ? text : removeWhitespace(text);
638    }
639
640    /**
641     * Split the template source into tags and literal text.
642     * @param source The sourcecode of the template
643     * @param startdelim The start delimiter for template tags (usually {@code "<?"})
644     * @param enddelim The end delimiter for template tags (usually {@code "?>"})
645     * @return A list of {@link Location} objects
646     */
647    public List<Location> tokenizeTags(String source, String startdelim, String enddelim)
648    {
649        Pattern tagPattern = Pattern.compile(escapeREchars(startdelim) + "(printx|print|code|for|if|elif|else|end|break|continue|def|return|note)(\\s*(.*?)\\s*)?" + escapeREchars(enddelim), Pattern.DOTALL);
650        LinkedList<Location> tags = new LinkedList<Location>();
651        if (source != null)
652        {
653            Matcher matcher = tagPattern.matcher(source);
654            int pos = 0;
655
656            int start;
657            int end;
658            while (matcher.find())
659            {
660                start = matcher.start();
661                end = start + matcher.group().length();
662                if (pos != start)
663                    tags.add(new Location(this, source, null, pos, start, pos, start));
664                int codestart = matcher.start(3);
665                int codeend = codestart + matcher.group(3).length();
666                String type = matcher.group(1);
667                if (!type.equals("note"))
668                    tags.add(new Location(this, source, matcher.group(1), start, end, codestart, codeend));
669                pos = end;
670            }
671            end = source.length();
672            if (pos != end)
673                tags.add(new Location(this, source, null, pos, end, pos, end));
674        }
675        return tags;
676    }
677
678    private static String escapeREchars(String input)
679    {
680        int len = input.length();
681
682        StringBuilder buffer = new StringBuilder(len);
683
684        for (int i = 0; i < len; ++i)
685        {
686            char c = input.charAt(i);
687            if (!(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9')))
688                buffer.append('\\');
689            buffer.append(c);
690        }
691        return buffer.toString();
692    }
693
694    public void finish(Location endlocation)
695    {
696        super.finish(endlocation);
697        String type = endlocation.getCode().trim();
698        if (type != null && type.length() != 0 && !type.equals("def"))
699            throw new BlockException("def ended by end" + type);
700    }
701
702    public boolean handleLoopControl(String name)
703    {
704        throw new BlockException(name + " outside of for loop");
705    }
706
707    static
708    {
709        Utils.register("de.livinglogic.ul4.location", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Location(null, null, null, -1, -1, -1, -1); }});
710        Utils.register("de.livinglogic.ul4.text", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Text(null, -1, -1); }});
711        Utils.register("de.livinglogic.ul4.const", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Const(null, -1, -1, null); }});
712        Utils.register("de.livinglogic.ul4.list", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.List(null, -1, -1); }});
713        Utils.register("de.livinglogic.ul4.listcomp", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.ListComprehension(null, -1, -1, null, null, null, null); }});
714        Utils.register("de.livinglogic.ul4.dict", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Dict(null, -1, -1); }});
715        Utils.register("de.livinglogic.ul4.dictcomp", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.DictComprehension(null, -1, -1, null, null, null, null, null); }});
716        Utils.register("de.livinglogic.ul4.genexpr", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.GeneratorExpression(null, -1, -1, null, null, null, null); }});
717        Utils.register("de.livinglogic.ul4.var", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Var(null, -1, -1, null); }});
718        Utils.register("de.livinglogic.ul4.ieie", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.ConditionalBlockBlock(null, -1, -1); }});
719        Utils.register("de.livinglogic.ul4.if", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.If(null, -1, -1, null); }});
720        Utils.register("de.livinglogic.ul4.elif", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.ElIf(null, -1, -1, null); }});
721        Utils.register("de.livinglogic.ul4.else", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Else(null, -1, -1); }});
722        Utils.register("de.livinglogic.ul4.for", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.For(null, -1, -1, null, null); }});
723        Utils.register("de.livinglogic.ul4.break", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Break(null, -1, -1); }});
724        Utils.register("de.livinglogic.ul4.continue", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Continue(null, -1, -1); }});
725        Utils.register("de.livinglogic.ul4.attr", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Attr(null, -1, -1, null, null); }});
726        Utils.register("de.livinglogic.ul4.slice", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Slice(null, -1, -1, null, null, null); }});
727        Utils.register("de.livinglogic.ul4.not", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Not(null, -1, -1, null); }});
728        Utils.register("de.livinglogic.ul4.ifexpr", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.IfExpression(null, -1, -1, null, null, null); }});
729        Utils.register("de.livinglogic.ul4.neg", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Neg(null, -1, -1, null); }});
730        Utils.register("de.livinglogic.ul4.print", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Print(null, -1, -1, null); }});
731        Utils.register("de.livinglogic.ul4.printx", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.PrintX(null, -1, -1, null); }});
732        Utils.register("de.livinglogic.ul4.return", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Return(null, -1, -1, null); }});
733        Utils.register("de.livinglogic.ul4.item", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Item(null, -1, -1, null, null); }});
734        Utils.register("de.livinglogic.ul4.eq", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.EQ(null, -1, -1, null, null); }});
735        Utils.register("de.livinglogic.ul4.ne", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.NE(null, -1, -1, null, null); }});
736        Utils.register("de.livinglogic.ul4.lt", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.LT(null, -1, -1, null, null); }});
737        Utils.register("de.livinglogic.ul4.le", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.LE(null, -1, -1, null, null); }});
738        Utils.register("de.livinglogic.ul4.gt", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.GT(null, -1, -1, null, null); }});
739        Utils.register("de.livinglogic.ul4.ge", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.GE(null, -1, -1, null, null); }});
740        Utils.register("de.livinglogic.ul4.contains", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Contains(null, -1, -1, null, null); }});
741        Utils.register("de.livinglogic.ul4.notcontains", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.NotContains(null, -1, -1, null, null); }});
742        Utils.register("de.livinglogic.ul4.add", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Add(null, -1, -1, null, null); }});
743        Utils.register("de.livinglogic.ul4.sub", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Sub(null, -1, -1, null, null); }});
744        Utils.register("de.livinglogic.ul4.mul", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Mul(null, -1, -1, null, null); }});
745        Utils.register("de.livinglogic.ul4.floordiv", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.FloorDiv(null, -1, -1, null, null); }});
746        Utils.register("de.livinglogic.ul4.truediv", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.TrueDiv(null, -1, -1, null, null); }});
747        Utils.register("de.livinglogic.ul4.or", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Or(null, -1, -1, null, null); }});
748        Utils.register("de.livinglogic.ul4.and", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.And(null, -1, -1, null, null); }});
749        Utils.register("de.livinglogic.ul4.mod", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Mod(null, -1, -1, null, null); }});
750        Utils.register("de.livinglogic.ul4.setvar", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.SetVar(null, -1, -1, null, null); }});
751        Utils.register("de.livinglogic.ul4.addvar", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.AddVar(null, -1, -1, null, null); }});
752        Utils.register("de.livinglogic.ul4.subvar", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.SubVar(null, -1, -1, null, null); }});
753        Utils.register("de.livinglogic.ul4.mulvar", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.MulVar(null, -1, -1, null, null); }});
754        Utils.register("de.livinglogic.ul4.floordivvar", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.FloorDivVar(null, -1, -1, null, null); }});
755        Utils.register("de.livinglogic.ul4.truedivvar", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.TrueDivVar(null, -1, -1, null, null); }});
756        Utils.register("de.livinglogic.ul4.modvar", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.ModVar(null, -1, -1, null, null); }});
757        Utils.register("de.livinglogic.ul4.call", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.Call(null, -1, -1, null); }});
758        Utils.register("de.livinglogic.ul4.template", new ObjectFactory(){ public UL4ONSerializable create() { return new com.livinglogic.ul4.InterpretedTemplate(null, null, null, false, null, null); }});
759    }
760
761    public void dumpUL4ON(Encoder encoder) throws IOException
762    {
763        encoder.dump(VERSION);
764        encoder.dump(source);
765        encoder.dump(name);
766        encoder.dump(keepWhitespace);
767        encoder.dump(startdelim);
768        encoder.dump(enddelim);
769        super.dumpUL4ON(encoder);
770    }
771
772    public void loadUL4ON(Decoder decoder) throws IOException
773    {
774        String version = (String)decoder.load();
775        if (!VERSION.equals(version))
776        {
777            throw new RuntimeException("Invalid version, expected " + VERSION + ", got " + version);
778        }
779        source = (String)decoder.load();
780        name = (String)decoder.load();
781        keepWhitespace = (Boolean)decoder.load();
782        startdelim = (String)decoder.load();
783        enddelim = (String)decoder.load();
784        super.loadUL4ON(decoder);
785    }
786
787    private static class BoundMethodRenderS extends BoundMethodWithContext<InterpretedTemplate>
788    {
789        private static final Signature signature = new Signature("renders", "kwargs", Signature.remainingKeywordArguments);
790
791        public BoundMethodRenderS(InterpretedTemplate object)
792        {
793            super(object);
794        }
795
796        public Signature getSignature()
797        {
798            return signature;
799        }
800
801        public Object callUL4(EvaluationContext context, Object[] args)
802        {
803            return object.renders(context, (Map<String, Object>)args[0]);
804        }
805    }
806
807    private static class BoundMethodRender extends BoundMethodWithContext<InterpretedTemplate>
808    {
809        private static final Signature signature = new Signature("render", "kwargs", Signature.remainingKeywordArguments);
810
811        public BoundMethodRender(InterpretedTemplate object)
812        {
813            super(object);
814        }
815
816        public Signature getSignature()
817        {
818            return signature;
819        }
820
821        public Object callUL4(EvaluationContext context, Object[] args)
822        {
823            object.render(context, (Map<String, Object>)args[0]);
824            return null;
825        }
826    }
827
828    protected static Set<String> attributes = makeExtendedSet(Block.attributes, "name", "keepws", "startdelim", "enddelim", "source", "render", "renders");
829
830    public Set<String> getAttributeNamesUL4()
831    {
832        return attributes;
833    }
834
835    public Object getItemStringUL4(String key)
836    {
837        if ("name".equals(key))
838            return name;
839        else if ("keepws".equals(key))
840            return keepWhitespace;
841        else if ("startdelim".equals(key))
842            return startdelim;
843        else if ("enddelim".equals(key))
844            return enddelim;
845        else if ("source".equals(key))
846            return source;
847        else if ("render".equals(key))
848            return new BoundMethodRender(this);
849        else if ("renders".equals(key))
850            return new BoundMethodRenderS(this);
851        else
852            return super.getItemStringUL4(key);
853    }
854}
Note: See TracBrowser for help on using the browser.