/*
 * 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
 *
 *      https://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.parser;

/**
 * A class originally generated by JJTree with the following JavaCCOptions:
 * MULTI=true,NODE_USES_PARSER=true,VISITOR=true,TRACK_TOKENS=false,NODE_PREFIX=AST,NODE_EXTENDS=,NODE_FACTORY=
 *
 * Works around issue https://javacc.dev.java.net/issues/show_bug.cgi?id=227
 * As soon as this issue if fixed and the maven plugin uses the correct version of Javacc, this
 * class can go away.
 *
 * The technical goal is to ensure every reference made in the parser was to a JexlNode; unfortunately,
 * as in javacc 4.1, it still uses a SimpleNode reference in the generated ParserVisitor.
 * Besides, there is no need to keep the parser around in the node.
 *
 * The functional goal is to a allow a <em>volatile</em> value in the node
 * so it can serve as a last evaluation cache even in multi-threaded executions.
 */
public class SimpleNode implements Node {

    /**
     */
    private static final long serialVersionUID = 1L;

    /** The parent node. */
    private JexlNode parent;

    /** The array of children nodes. */
    private JexlNode[] children;

    /** The node type id. */
    protected final int id;

    /** Volatile value so it can be used as a last evaluation cache. */
    private transient volatile Object value;

    /**
     * Creates a SimpleNode instance.
     *
     * @param i the node type identifier
     */
    public SimpleNode(final int i) {
        id = i;
    }

    /**
     * Constructs a SimpleNode instance.
     *
     * @param p not used.
     * @param i the node type identifier
     * @deprecated Use {@link #SimpleNode(int)}.
     */
    @Deprecated
    public SimpleNode(final Parser p, final int i) {
        this(i);
    }

    /**
     * Accepts the visitor on all this node's children.
     *
     * @param visitor the visitor
     * @param data contextual data
     * @return result of visit
     **/
    public Object childrenAccept(final ParserVisitor visitor, final Object data) {
        if (children != null) {
            for (final JexlNode child : children) {
                child.jjtAccept(visitor, data);
            }
        }
        return data;
    }

    /* Override this method if you want to customize how the JexlNode dumps
    out its children. */
    public void dump(final String prefix) {
        dumpOut(toString(prefix));
        if (children != null) {
            for (final SimpleNode n : children) {
                if (n != null) {
                    n.dump(prefix + " ");
                }
            }
        }
    }

    /**
     * Override to dump output somewhere.
     *
     * @param str the string to output
     */
    protected void dumpOut(final String str) {
        // override to obtain an output
    }

    @Override
    public int getId() {
        return id;
    }

    /**
     * Accepts the visitor.
     *
     * @param visitor the visitor
     * @param data contextual data
     * @return result of visit
     **/
    @Override
    public Object jjtAccept(final ParserVisitor visitor, final Object data) {
        return visitor.visit(this, data);
    }

    /**
     * Adds a child node.
     *
     * @param n the child node
     * @param i the child offset
     */
    @Override
    public void jjtAddChild(final Node n, final int i) {
        if (children == null) {
            children = new JexlNode[i + 1];
        } else if (i >= children.length) {
            final JexlNode[] c = new JexlNode[i + 1];
            System.arraycopy(children, 0, c, 0, children.length);
            children = c;
        }
        children[i] = (JexlNode) n;
    }

    @Override
    public void jjtClose() {
    }

    /**
     * Gets a child of this node.
     *
     * @param i the child offset
     * @return the child node
     */
    @Override
    public JexlNode jjtGetChild(final int i) {
        return children[i];
    }

    /**
     * Gets this node number of children.
     *
     * @return the number of children
     */
    @Override
    public int jjtGetNumChildren() {
        return children == null ? 0 : children.length;
    }

    /**
     * Gets this node's parent.
     *
     * @return the parent node
     */
    @Override
    public JexlNode jjtGetParent() {
        return parent;
    }

    /**
     * Gets this node value.
     *
     * @return value
     */
    public Object jjtGetValue() {
        return value;
    }

    @Override
    public void jjtOpen() {
    }

    // For use by ASTJexlScript only
    void jjtSetChildren(final JexlNode[] jexlNodes) {
        children = jexlNodes;
    }

    /**
     * Sets this node's parent.
     *
     * @param n the parent
     */
    @Override
    public void jjtSetParent(final Node n) {
        parent = (JexlNode) n;
    }

    /**
     * Sets this node value.
     *
     * @param value this node value.
     */
    public void jjtSetValue(final Object value) {
        this.value = value;
    }

    /* You can override these two methods in subclasses of SimpleNode to
    customize the way the JexlNode 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. */
    @Override
    public String toString() {
        return ParserTreeConstants.jjtNodeName[id];
    }

    public String toString(final String prefix) {
        return prefix + toString();
    }
}

/* JavaCC - OriginalChecksum=7dff880883d088a37c1e3197e4b455a0 (do not edit this line) */
