aboutsummaryrefslogtreecommitdiff
path: root/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/SimpleNode.java
diff options
context:
space:
mode:
Diffstat (limited to 'velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/SimpleNode.java')
-rw-r--r--velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/SimpleNode.java650
1 files changed, 650 insertions, 0 deletions
diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/SimpleNode.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/SimpleNode.java
new file mode 100644
index 00000000..f85d6926
--- /dev/null
+++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/SimpleNode.java
@@ -0,0 +1,650 @@
+package org.apache.velocity.runtime.parser.node;
+
+/*
+ * 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.
+ */
+
+
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.nio.charset.Charset;
+
+import org.apache.velocity.Template;
+import org.apache.velocity.context.InternalContextAdapter;
+import org.apache.velocity.exception.MethodInvocationException;
+import org.apache.velocity.exception.ParseErrorException;
+import org.apache.velocity.exception.ResourceNotFoundException;
+import org.apache.velocity.exception.TemplateInitException;
+import org.apache.velocity.runtime.RuntimeConstants;
+import org.apache.velocity.runtime.RuntimeServices;
+import org.apache.velocity.runtime.parser.Parser;
+import org.apache.velocity.runtime.parser.Token;
+import org.apache.velocity.util.StringUtils;
+
+import org.slf4j.Logger;
+
+/**
+ *
+ */
+public class SimpleNode implements Node, Cloneable
+{
+ /** */
+ protected RuntimeServices rsvc = null;
+
+ /** */
+ protected Logger log = null;
+
+ /** */
+ protected Node parent;
+
+ /** */
+ protected Node[] children;
+
+ /** */
+ protected int id;
+
+ /** */
+ protected Parser parser;
+
+ /** */
+ protected int info;
+
+ /** */
+ public boolean state;
+
+ /** */
+ protected boolean invalid = false;
+
+ /** */
+ protected Token first;
+
+ /** */
+ protected Token last;
+
+ protected Template template;
+
+ /**
+ * For caching the literal value.
+ */
+ protected String literal = null;
+
+ /**
+ * Line number for this Node in the vm source file.
+ */
+
+ protected int line;
+
+ /**
+ * Column number for this Node in the vm source file.
+ */
+ protected int column;
+
+ /**
+ * String image variable of the first Token element that was parsed and connected to this Node.
+ */
+ protected String firstImage;
+
+ /**
+ * String image variable of the last Token element that was parsed and connected to this Node.
+ */
+ protected String lastImage;
+
+ public RuntimeServices getRuntimeServices()
+ {
+ return rsvc;
+ }
+
+ /**
+ * @param i
+ */
+ public SimpleNode(int i)
+ {
+ id = i;
+ }
+
+ /**
+ * @param p
+ * @param i
+ */
+ public SimpleNode(Parser p, int i)
+ {
+ this(i);
+ parser = p;
+ template = parser.getCurrentTemplate();
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#jjtOpen()
+ */
+ @Override
+ public void jjtOpen()
+ {
+ first = parser.getToken(1); // added
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#jjtClose()
+ */
+ @Override
+ public void jjtClose()
+ {
+ last = parser.getToken(0); // added
+ }
+
+ /**
+ * @param t
+ */
+ public void setFirstToken(Token t)
+ {
+ this.first = t;
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#getFirstToken()
+ */
+ @Override
+ public Token getFirstToken()
+ {
+ return first;
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#getLastToken()
+ */
+ @Override
+ public Token getLastToken()
+ {
+ return last;
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#jjtSetParent(org.apache.velocity.runtime.parser.node.Node)
+ */
+ @Override
+ public void jjtSetParent(Node n)
+ {
+ parent = n;
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#jjtGetParent()
+ */
+ @Override
+ public Node jjtGetParent()
+ {
+ return parent;
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#jjtAddChild(org.apache.velocity.runtime.parser.node.Node, int)
+ */
+ @Override
+ public void jjtAddChild(Node n, int i)
+ {
+ if (children == null)
+ {
+ children = new Node[i + 1];
+ }
+ else if (i >= children.length)
+ {
+ Node c[] = new Node[i + 1];
+ System.arraycopy(children, 0, c, 0, children.length);
+ children = c;
+ }
+ children[i] = n;
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#jjtGetChild(int)
+ */
+ @Override
+ public Node jjtGetChild(int i)
+ {
+ return children[i];
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#jjtGetNumChildren()
+ */
+ @Override
+ public int jjtGetNumChildren()
+ {
+ return (children == null) ? 0 : children.length;
+ }
+
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#jjtAccept(org.apache.velocity.runtime.parser.node.ParserVisitor, java.lang.Object)
+ */
+ @Override
+ public Object jjtAccept(ParserVisitor visitor, Object data)
+ {
+ return visitor.visit(this, data);
+ }
+
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#childrenAccept(org.apache.velocity.runtime.parser.node.ParserVisitor, java.lang.Object)
+ */
+ @Override
+ public Object childrenAccept(ParserVisitor visitor, Object data)
+ {
+ if (children != null)
+ {
+ for (Node aChildren : children)
+ {
+ aChildren.jjtAccept(visitor, data);
+ }
+ }
+ return data;
+ }
+
+ /* You can override these two methods in subclasses of SimpleNode to
+ customize the way the node appears when the tree is dumped. If
+ your output uses more than one line you should override
+ toString(String), otherwise overriding toString() is probably all
+ you need to do. */
+ /**
+ * @param prefix display prefix
+ * @return String representation of this node.
+ */
+ public String toString(String prefix)
+ {
+ return prefix + "_" + toString();
+ }
+
+ /**
+ * <p>Dumps nodes tree on System.out.</p>
+ * <p>Override {@link #dump(String, PrintWriter)} if you want to customize
+ * how the node dumps out its children.
+ *
+ * @param prefix
+ */
+ public final void dump(String prefix)
+ {
+ dump(prefix, System.out);
+ }
+
+ /**
+ * <p>Dumps nodes tree on System.out.</p>
+ * <p>Override {@link #dump(String, PrintWriter)} if you want to customize
+ * how the node dumps out its children.
+ *
+ * @param prefix display prefix
+ * @param out output print stream
+ */
+ public final void dump(String prefix, PrintStream out)
+ {
+ Charset charset = null;
+ if (rsvc != null) /* may be null if node isn't yet initialized */
+ {
+ String encoding = rsvc.getString(RuntimeConstants.INPUT_ENCODING);
+ try
+ {
+ charset = Charset.forName(encoding);
+ }
+ catch (Exception e) {}
+ }
+ if (charset == null)
+ {
+ charset = Charset.defaultCharset();
+ }
+ PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, charset));
+ dump(prefix, pw);
+ pw.flush();
+ }
+
+ /**
+ * <p>Dumps nodes tree on System.out.</p>
+ * <p>Override this method if you want to customize how the node dumps
+ * out its children.</p>
+ *
+ * @param prefix display prefix
+ * @param out output print writer
+ */
+ public void dump(String prefix, PrintWriter out)
+ {
+ out.println(toString());
+ if (children != null)
+ {
+ for (int i = 0; i < children.length; ++i)
+ {
+ SimpleNode n = (SimpleNode) children[i];
+ out.print(prefix + " |_");
+ if (n != null)
+ {
+ n.dump(prefix + ( i == children.length - 1 ? " " : " | " ), out);
+ }
+ }
+ }
+ }
+
+ /**
+ * Return a string that tells the current location of this node.
+ * @param context
+ * @return location
+ */
+ protected String getLocation(InternalContextAdapter context)
+ {
+ return StringUtils.formatFileString(this);
+ }
+
+ // All additional methods
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#literal()
+ */
+ @Override
+ public String literal()
+ {
+ if( literal != null )
+ {
+ return literal;
+ }
+
+ // if we have only one string, just return it and avoid
+ // buffer allocation. VELOCITY-606
+ if (first == last)
+ {
+ literal = NodeUtils.tokenLiteral(parser, first);
+ return literal;
+ }
+
+ Token t = first;
+ StringBuilder sb = new StringBuilder(NodeUtils.tokenLiteral(parser, t));
+ while (t != last)
+ {
+ t = t.next;
+ sb.append(NodeUtils.tokenLiteral(parser, t));
+ }
+ literal = sb.toString();
+ return literal;
+ }
+
+ /**
+ * @throws TemplateInitException
+ * @see org.apache.velocity.runtime.parser.node.Node#init(org.apache.velocity.context.InternalContextAdapter, java.lang.Object)
+ */
+ @Override
+ public Object init(InternalContextAdapter context, Object data) throws TemplateInitException
+ {
+ /*
+ * hold onto the RuntimeServices
+ */
+
+ rsvc = (RuntimeServices) data;
+ log = rsvc.getLog("rendering");
+
+ int i, k = jjtGetNumChildren();
+
+ for (i = 0; i < k; i++)
+ {
+ jjtGetChild(i).init( context, data);
+ }
+
+ line = first.beginLine;
+ column = first.beginColumn;
+
+ return data;
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#evaluate(org.apache.velocity.context.InternalContextAdapter)
+ */
+ @Override
+ public boolean evaluate(InternalContextAdapter context)
+ throws MethodInvocationException
+ {
+ return false;
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#value(org.apache.velocity.context.InternalContextAdapter)
+ */
+ @Override
+ public Object value(InternalContextAdapter context)
+ throws MethodInvocationException
+ {
+ return null;
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#render(org.apache.velocity.context.InternalContextAdapter, java.io.Writer)
+ */
+ @Override
+ public boolean render(InternalContextAdapter context, Writer writer)
+ throws IOException, MethodInvocationException, ParseErrorException, ResourceNotFoundException
+ {
+ int i, k = jjtGetNumChildren();
+
+ for (i = 0; i < k; i++)
+ jjtGetChild(i).render(context, writer);
+
+ return true;
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#execute(java.lang.Object, org.apache.velocity.context.InternalContextAdapter)
+ */
+ @Override
+ public Object execute(Object o, InternalContextAdapter context)
+ throws MethodInvocationException
+ {
+ return null;
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#getType()
+ */
+ @Override
+ public int getType()
+ {
+ return id;
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#setInfo(int)
+ */
+ @Override
+ public void setInfo(int info)
+ {
+ this.info = info;
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#getInfo()
+ */
+ @Override
+ public int getInfo()
+ {
+ return info;
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#setInvalid()
+ */
+ @Override
+ public void setInvalid()
+ {
+ invalid = true;
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#isInvalid()
+ */
+ @Override
+ public boolean isInvalid()
+ {
+ return invalid;
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#getLine()
+ */
+ @Override
+ public int getLine()
+ {
+ return line;
+ }
+
+ /**
+ * @see org.apache.velocity.runtime.parser.node.Node#getColumn()
+ */
+ @Override
+ public int getColumn()
+ {
+ return column;
+ }
+
+ /**
+ * @since 1.5
+ */
+ public String toString()
+ {
+ StringBuilder tokens = new StringBuilder();
+
+ for (Token t = getFirstToken(); t != null; )
+ {
+ tokens.append("[").append(t.image.replace("\n", "\\n")).append("]");
+ if (t.next != null)
+ {
+ if (t.equals(getLastToken()))
+ {
+ break;
+ }
+ else
+ {
+ tokens.append(", ");
+ }
+ }
+ t = t.next;
+ }
+ String tok = tokens.toString();
+ if (tok.length() > 50) tok = tok.substring(0, 50) + "...";
+ return getClass().getSimpleName() + " [id=" + id + ", info=" + info + ", invalid="
+ + invalid
+ + ", tokens=" + tok + "]";
+ }
+
+ @Override
+ public String getTemplateName()
+ {
+ return template.getName();
+ }
+
+ /**
+ * Call before calling cleanupParserAndTokens() if you want to store image of
+ * the first and last token of this node.
+ */
+ public void saveTokenImages()
+ {
+ if( first != null )
+ {
+ this.firstImage = first.image;
+ }
+ if( last != null )
+ {
+ this.lastImage = last.image;
+ }
+ }
+
+ /**
+ * Removes references to Parser and Tokens since they are not needed anymore at this point.
+ *
+ * This allows us to save memory quite a bit.
+ */
+ public void cleanupParserAndTokens()
+ {
+ this.parser = null;
+ this.first = null;
+ this.last = null;
+ }
+
+ /**
+ * @return String image variable of the first Token element that was parsed and connected to this Node.
+ */
+ @Override
+ public String getFirstTokenImage()
+ {
+ return firstImage;
+ }
+
+ /**
+ * @return String image variable of the last Token element that was parsed and connected to this Node.
+ */
+ @Override
+ public String getLastTokenImage()
+ {
+ return lastImage;
+ }
+
+ @Override
+ public Template getTemplate() { return template; }
+
+ /**
+ * @return the parser which created this node
+ * @since 2.2
+ */
+ @Override
+ public Parser getParser()
+ {
+ return parser;
+ }
+
+ /**
+ * Root node deep cloning
+ * @param template owner template
+ * @return cloned node
+ * @throws CloneNotSupportedException
+ * @since 2.4
+ */
+ public Node clone(Template template) throws CloneNotSupportedException
+ {
+ if (parent != null) {
+ throw new IllegalStateException("cannot clone a child node without knowing its parent");
+ }
+ return clone(template, null);
+ }
+
+ /**
+ * Child node deep cloning
+ * @param template owner template
+ * @param parent parent node
+ * @return cloned node
+ * @throws CloneNotSupportedException
+ * @since 2.4
+ */
+ protected Node clone(Template template, Node parent) throws CloneNotSupportedException
+ {
+ SimpleNode clone = (SimpleNode)super.clone();
+ clone.template = template;
+ clone.parent = parent;
+ if (children != null)
+ {
+ clone.children = new SimpleNode[children.length];
+ for (int i = 0; i < children.length; ++i)
+ {
+ clone.children[i] = ((SimpleNode)children[i]).clone(template, clone);
+ }
+ }
+ return clone;
+ }
+}