package de.uni_hildesheim.sse.trans.convert;

import de.uni_hildesheim.sse.model.cst.Comment;
import de.uni_hildesheim.sse.model.cst.CompoundAccess;
import de.uni_hildesheim.sse.model.cst.CompoundInitializer;
import de.uni_hildesheim.sse.model.cst.ConstantValue;
import de.uni_hildesheim.sse.model.cst.ContainerInitializer;
import de.uni_hildesheim.sse.model.cst.ContainerOperationCall;
import de.uni_hildesheim.sse.model.cst.IConstraintTreeVisitor;
import de.uni_hildesheim.sse.model.cst.IfThen;
import de.uni_hildesheim.sse.model.cst.Let;
import de.uni_hildesheim.sse.model.cst.OCLFeatureCall;
import de.uni_hildesheim.sse.model.cst.Parenthesis;
import de.uni_hildesheim.sse.model.cst.UnresolvedExpression;
import de.uni_hildesheim.sse.model.cst.Variable;
import de.uni_hildesheim.sse.model.varModel.Constraint;
import de.uni_hildesheim.sse.model.varModel.datatypes.OclKeyWords;

/**
 * Checks whether a given Constraint is a disjunction.
 * 
 * @author El-Sharkawy
 * 
 */
class DisjunctionChecker implements IConstraintTreeVisitor {

    private boolean isDisjunctionTerm;

    /**
     * Sole constructor for this class,
     * will check whether the given constraint is a disjunction term.
     * @param constraint The constraint to check. This constraint can only contain AND, OR, and NOT operations,
     *     otherwise this checker will not work.
     * @see #isDisjunctionTerm()
     */
    DisjunctionChecker(Constraint constraint) {
        isDisjunctionTerm = true;
        constraint.getConsSyntax().accept(this);
    }
    
    /**
     * Returns whether the given constraint is a disjunction term.
     * @return <tt>true</tt> if the given constraint is a disjunction term,
     * <tt>false</tt> otherwise.
     */
    boolean isDisjunctionTerm() {
        return isDisjunctionTerm;
    }

    @Override
    public void visitConstantValue(ConstantValue value) {
        // Nothing to do, end here
    }

    @Override
    public void visitVariable(Variable variable) {
        // Nothing to do, end here
    }

    @Override
    public void visitParenthesis(Parenthesis parenthesis) {
        parenthesis.getExpr().accept(this);
    }

    @Override
    public void visitComment(Comment comment) {
        // Nothing to do, end here
    }

    @Override
    public void visitOclFeatureCall(OCLFeatureCall call) {
        String operation = call.getOperation();
        if (OclKeyWords.OR.equals(operation) || OclKeyWords.NOT.equals(operation)) {
            call.getOperand().accept(this);
            for (int i = 0, n = call.getParameterCount(); i < n; i++) {
                call.getParameter(i).accept(this);
            }
        } else {
            isDisjunctionTerm = false;
        }
    }

    @Override
    public void visitLet(Let let) {
        // Not supported by this Translator
        isDisjunctionTerm = false;
    }

    @Override
    public void visitIfThen(IfThen ifThen) {
        // Not supported by this Translator
        isDisjunctionTerm = false;
    }

    @Override
    public void visitContainerOperationCall(ContainerOperationCall call) {
        // Not supported by this Translator
        isDisjunctionTerm = false;
    }

    @Override
    public void visitCompoundAccess(CompoundAccess access) {
        // Not supported by this Translator
        isDisjunctionTerm = false;
    }

    @Override
    public void visitUnresolvedExpression(UnresolvedExpression expression) {
        // Not supported by this Translator
        isDisjunctionTerm = false;
    }

    @Override
    public void visitCompoundInitializer(CompoundInitializer initializer) {
         // Not supported by this Translator
        isDisjunctionTerm = false;
    }

    @Override
    public void visitContainerInitializer(ContainerInitializer initializer) {
        // Not supported by this Translator
        isDisjunctionTerm = false;
    }

}
