/**
 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
 */

package net.sourceforge.pmd.lang.modelica.ast;

import net.sourceforge.pmd.lang.ast.AstVisitor;
import net.sourceforge.pmd.lang.ast.impl.javacc.AbstractJjtreeNode;
import net.sourceforge.pmd.lang.modelica.resolver.ModelicaScope;

/**
 * Abstract base class for all nodes parsed by {@link ModelicaParser}.
 *
 * Please note that some of these nodes are autogenerated and placed to
 * <code>pmd-modelica/target/generated-sources/javacc</code> by the build script. Those
 * located here are deleted from autogenerated sources after build.
 *
 * @see ModelicaNode for public API.
 */
abstract class AbstractModelicaNode extends AbstractJjtreeNode<AbstractModelicaNode, ModelicaNode> implements ModelicaNode {

    private ModelicaScope ownScope;

    AbstractModelicaNode(int id) {
        super(id);
    }


    @Override // override to make protected member accessible to parser
    protected void setImage(String image) {
        super.setImage(image);
    }


    @Override
    @SuppressWarnings("unchecked")
    public final <P, R> R acceptVisitor(AstVisitor<? super P, ? extends R> visitor, P data) {
        if (visitor instanceof ModelicaVisitor) {
            return acceptModelicaVisitor((ModelicaVisitor<? super P, ? extends R>) visitor, data);
        }
        return visitor.cannotVisit(this, data);
    }

    protected abstract <P, R> R acceptModelicaVisitor(ModelicaVisitor<? super P, ? extends R> visitor, P data);

    @Override
    public String getXPathNodeName() {
        return getClass().getSimpleName().substring(3);
    }

    @Override
    public ModelicaScope getContainingScope() {
        return getParent().getMostSpecificScope();
    }

    @Override
    public ModelicaScope getMostSpecificScope() {
        if (ownScope == null) {
            return getContainingScope();
        } else {
            return ownScope;
        }
    }

    /**
     * For resolver, set the lexical scope defined by this node, if any.
     *
     * @param scope Scope defined by this specific node
     */
    void setOwnScope(ModelicaScope scope) {
        ownScope = scope;
    }
}
