Home | History | Annotate | Download | only in interpreter
      1 /*
      2  * Copyright (C) 2010 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.clearsilver.jsilver.interpreter;
     18 
     19 import com.google.clearsilver.jsilver.autoescape.EscapeMode;
     20 import com.google.clearsilver.jsilver.data.Data;
     21 import com.google.clearsilver.jsilver.exceptions.JSilverInterpreterException;
     22 import com.google.clearsilver.jsilver.resourceloader.ResourceLoader;
     23 import com.google.clearsilver.jsilver.syntax.node.PCommand;
     24 import com.google.clearsilver.jsilver.template.Macro;
     25 import com.google.clearsilver.jsilver.template.RenderingContext;
     26 import com.google.clearsilver.jsilver.template.Template;
     27 
     28 import java.io.IOException;
     29 
     30 /**
     31  * User defined macro that will be executed by the interpreter.
     32  *
     33  * NOTE: This is not thread safe and cannot be shared between RenderingContexts. This is taken care
     34  * of by the TemplateInterpreter.
     35  */
     36 public class InterpretedMacro implements Macro {
     37 
     38   private final PCommand command;
     39   private final Template owningTemplate;
     40   private final String macroName;
     41   private final String[] argumentNames;
     42   private final TemplateInterpreter templateInterpreter;
     43   private final RenderingContext owningContext;
     44 
     45   public InterpretedMacro(PCommand command, Template owningTemplate, String macroName,
     46       String[] argumentNames, TemplateInterpreter templateInterpreter,
     47       RenderingContext owningContext) {
     48     this.command = command;
     49     this.owningTemplate = owningTemplate;
     50     this.macroName = macroName;
     51     this.argumentNames = argumentNames;
     52     this.templateInterpreter = templateInterpreter;
     53     this.owningContext = owningContext;
     54   }
     55 
     56   @Override
     57   public void render(RenderingContext context) throws IOException {
     58     assert context == owningContext : "Cannot render macro defined in another context";
     59     context.pushExecutionContext(this);
     60     boolean doRuntimeAutoEscaping = !(context.isRuntimeAutoEscaping());
     61     if (doRuntimeAutoEscaping) {
     62       context.startRuntimeAutoEscaping();
     63     }
     64     command.apply(templateInterpreter);
     65     if (doRuntimeAutoEscaping) {
     66       context.stopRuntimeAutoEscaping();
     67     }
     68     context.popExecutionContext();
     69   }
     70 
     71   @Override
     72   public void render(Data data, Appendable out, ResourceLoader resourceLoader) throws IOException {
     73     render(createRenderingContext(data, out, resourceLoader));
     74   }
     75 
     76   @Override
     77   public RenderingContext createRenderingContext(Data data, Appendable out,
     78       ResourceLoader resourceLoader) {
     79     return owningTemplate.createRenderingContext(data, out, resourceLoader);
     80   }
     81 
     82   @Override
     83   public String getTemplateName() {
     84     return owningTemplate.getTemplateName();
     85   }
     86 
     87   @Override
     88   public EscapeMode getEscapeMode() {
     89     return owningTemplate.getEscapeMode();
     90   }
     91 
     92   @Override
     93   public String getDisplayName() {
     94     return owningTemplate.getDisplayName() + ":" + macroName;
     95   }
     96 
     97   @Override
     98   public String getMacroName() {
     99     return macroName;
    100   }
    101 
    102   @Override
    103   public String getArgumentName(int index) {
    104     if (index >= argumentNames.length) {
    105       // TODO: Make sure this behavior of failing if too many
    106       // arguments are passed to a macro is consistent with JNI / interpreter.
    107       throw new JSilverInterpreterException("Too many arguments supplied to macro " + macroName);
    108     }
    109     return argumentNames[index];
    110   }
    111 
    112   @Override
    113   public int getArgumentCount() {
    114     return argumentNames.length;
    115   }
    116 }
    117