// $Id: LogicalOperatorWithTwoFormulas.java,v 1.6 2004/02/27 16:30:00 m31 Exp $
//
// This file is part of the program suite "Principia Mathematica II"
// which is a working prototype for the main project:
// "Hilbert II" - http://www.qedeq.org
//
// Copyright 2001-2004  Michael Meyling <mime@qedeq.org>.
//
// "Principia Mathematica II" is free software; you can redistribute
// it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

package com.meyling.principia.logic.basic;


import com.meyling.principia.argument.Argument;
import com.meyling.principia.argument.ArgumentException;


/**
 * LogicalOperatorWithTwoFormulas of formulas.
 * @version $Revision: 1.6 $
 * @author  Michael Meyling
 */
public abstract class LogicalOperatorWithTwoFormulas
        extends AbstractFormula
        implements Argument, Formula {

    /** first part formula */
    private final Formula formula1;

    /** second part formula */
    private final Formula formula2;

    /**
     * Constructs a new formula out of two given ones.
     *
     * @param   arguments    must contain two formulas
     * @throws  ArgumentException
     *          if same subject variable exists
     *          bound and unbound, or argument dosn't
     *          consist of two formulas
     *
     */
    public LogicalOperatorWithTwoFormulas(final Argument[] arguments)
            throws ArgumentException {
        super(arguments);
        if (arguments.length != 2) {
            throw new ArgumentException(
                BasicConstants.CODE_CONSTRUCTOR_WRONG_ARGUMENT_NUMBER,
                BasicCreator.getName(this.getClass())
                + BasicConstants.OPERATOR_WITH_TWO_ARGUMENTS);
        }
        if (!(arguments[0] instanceof Formula)) {
            throw new ArgumentException(
                BasicConstants.CODE_CONSTRUCTOR_WRONG_ARGUMENT_TYPE,
                BasicCreator.getName(this.getClass())
                + BasicConstants.FIRST_ARGUMENT_TYPE
                + BasicConstants.FORMULA,
                arguments[0]);
        }
        if (!(arguments[1] instanceof Formula)) {
            throw new ArgumentException(
                BasicConstants.CODE_CONSTRUCTOR_WRONG_ARGUMENT_TYPE,
                BasicCreator.getName(this.getClass())
                + BasicConstants.SECOND_ARGUMENT_TYPE
                + BasicConstants.FORMULA,
                arguments[1]);
        }
        this.formula1 = (Formula) arguments[0];
        this.formula2 = (Formula) arguments[1];
        if (!formula1.getFreeSubjectVariables().emptyIntersection(
                formula2.getBoundSubjectVariables())
                || !formula1.getBoundSubjectVariables().emptyIntersection(
                formula2.getFreeSubjectVariables())) {
            throw new ArgumentException(
                BasicConstants.CODE_CONSTRUCTOR_ARGUMENT_CHECK_FAILED,
                BasicCreator.getName(this.getClass())
                + BasicConstants.MIXED_FREE_BOUND);
        }
    }


    /**
     * Constructs a new formula out of two given ones.
     *
     * @param   formula1    first formula
     * @param   formula2    second formula
     * @throws  ArgumentException
     *          if same subject variable exists
     *          bound and unbound
     *
     */
    public LogicalOperatorWithTwoFormulas(final Formula formula1,
            final Formula formula2)
            throws ArgumentException {
        this(new Argument[] { formula1, formula2} );

    }


    /**
     * @inherited
     * @return  always 2
     */
    public final int getPartFormulaSize() {
        return 2;
    }


    /** @inherited */
    public final Formula getPartFormula(final int i) {
        if (i == 0) {
            return formula1;
        } else if (i == 1) {
            return formula2;
        } else {
            throw new IllegalArgumentException(
                BasicConstants.WRONG_FORMULA_NUMBER + "{0, 1}");
        }
    }


    /** @inherited */
    public final SubjectVariables getFreeSubjectVariables() {
        final SubjectVariables variables
            = new SubjectVariables(formula1.getFreeSubjectVariables());
        variables.addAll(formula2.getFreeSubjectVariables());
        return variables;
    };


    /** @inherited */
    public final SubjectVariables getBoundSubjectVariables() {
        final SubjectVariables variables
            = new SubjectVariables(formula1.getBoundSubjectVariables());
        variables.addAll(formula2.getBoundSubjectVariables());
        return variables;
    }


    /** @inherited */
    public SubjectVariables getSubjectVariables() {
        final SubjectVariables variables
            = new SubjectVariables(formula1.getSubjectVariables());
        variables.addAll(formula2.getSubjectVariables());
        return variables;
    }


}
