All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.commons.jexl3.internal.TemplateInterpreter Maven / Gradle / Ivy

Go to download

The Apache Commons JEXL library is an implementation of the JSTL Expression Language with extensions.

There is a newer version: 3.4.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.jexl3.internal;

import org.apache.commons.jexl3.JexlContext;
import org.apache.commons.jexl3.JexlInfo;
import org.apache.commons.jexl3.JxltEngine;
import org.apache.commons.jexl3.internal.TemplateEngine.TemplateExpression;
import org.apache.commons.jexl3.introspection.JexlMethod;
import org.apache.commons.jexl3.introspection.JexlUberspect;
import org.apache.commons.jexl3.parser.ASTArguments;
import org.apache.commons.jexl3.parser.ASTFunctionNode;
import org.apache.commons.jexl3.parser.ASTIdentifier;
import org.apache.commons.jexl3.parser.JexlNode;
import java.io.Writer;
import java.util.Arrays;

/**
 * The type of interpreter to use during evaluation of templates.
 * 

This context exposes its writer as '$jexl' to the scripts.

*

public for introspection purpose.

*/ public class TemplateInterpreter extends Interpreter { /** The array of template expressions. */ private final TemplateExpression[] exprs; /** The writer used to output. */ private final Writer writer; /** * Creates a template interpreter instance. * @param jexl the engine instance * @param jcontext the base context * @param jframe the calling frame * @param expressions the list of TemplateExpression from the TemplateScript to evaluate * @param out the output writer */ TemplateInterpreter(Engine jexl, JexlContext jcontext, Scope.Frame jframe, TemplateExpression[] expressions, Writer out) { super(jexl, jcontext, jframe); exprs = expressions; writer = out; } /** * Includes a call to another template. *

* Includes another template using this template initial context and writer.

* @param script the TemplateScript to evaluate * @param args the arguments */ public void include(TemplateScript script, Object... args) { script.evaluate(context, writer, args); } /** * Prints a unified expression evaluation result. * @param e the expression number */ public void print(int e) { if (e < 0 || e >= exprs.length) { return; } TemplateEngine.TemplateExpression expr = exprs[e]; if (expr.isDeferred()) { expr = expr.prepare(frame, context); } if (expr instanceof TemplateEngine.CompositeExpression) { printComposite((TemplateEngine.CompositeExpression) expr); } else { doPrint(expr.getInfo(), expr.evaluate(this)); } } /** * Prints a composite expression. * @param composite the composite expression */ private void printComposite(TemplateEngine.CompositeExpression composite) { TemplateEngine.TemplateExpression[] cexprs = composite.exprs; final int size = cexprs.length; Object value; for (int e = 0; e < size; ++e) { value = cexprs[e].evaluate(this); doPrint(cexprs[e].getInfo(), value); } } /** * Prints to output. *

* This will dynamically try to find the best suitable method in the writer through uberspection. * Subclassing Writer by adding 'print' methods should be the preferred way to specialize output. *

* @param info the source info * @param arg the argument to print out */ private void doPrint(JexlInfo info, Object arg) { try { if (writer != null) { if (arg instanceof CharSequence) { writer.write(arg.toString()); } else if (arg != null) { Object[] value = {arg}; JexlUberspect uber = jexl.getUberspect(); JexlMethod method = uber.getMethod(writer, "print", value); if (method != null) { method.invoke(writer, value); } else { writer.write(arg.toString()); } } } } catch (java.io.IOException xio) { throw TemplateEngine.createException(info, "call print", null, xio); } catch (java.lang.Exception xany) { throw TemplateEngine.createException(info, "invoke print", null, xany); } } @Override protected Object resolveNamespace(String prefix, JexlNode node) { return "jexl".equals(prefix)? this : super.resolveNamespace(prefix, node); } @Override protected Object visit(ASTFunctionNode node, Object data) { int argc = node.jjtGetNumChildren(); if (argc > 2) { // objectNode 0 is the prefix String prefix = ((ASTIdentifier) node.jjtGetChild(0)).getName(); if ("jexl".equals(prefix)) { ASTIdentifier functionNode = (ASTIdentifier) node.jjtGetChild(1); ASTArguments argNode = (ASTArguments) node.jjtGetChild(2); String fname = functionNode.getName(); if ("print".equals(fname)) { // evaluate the arguments Object[] argv = visit(argNode, null); print((Integer) argv[0]); return null; } if ("include".equals(fname)) { // evaluate the arguments Object[] argv = visit(argNode, null); if (argv != null && argv.length > 0) { if (argv[0] instanceof TemplateScript) { TemplateScript script = (TemplateScript) argv[0]; if (argv.length > 1) { argv = Arrays.copyOfRange(argv, 1, argv.length); } else { argv = null; } include(script, argv); return null; } } } // fail safe throw new JxltEngine.Exception(node.jexlInfo(), "no callable template function " + fname, null); } } return super.visit(node, data); } @Override protected Object visit(ASTIdentifier node, Object data) { String name = node.getName(); if ("$jexl".equals(name)) { return writer; } return super.visit(node, data); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy