// $Id: Abbreviation.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.paragraph;


import com.meyling.principia.argument.AbstractArgumentList;
import com.meyling.principia.argument.Argument;
import com.meyling.principia.argument.ArgumentException;
import com.meyling.principia.argument.PatternVariable;
import com.meyling.principia.argument.PatternVariables;
import com.meyling.principia.logic.basic.Formula;
import com.meyling.principia.module.Module;
import com.meyling.principia.module.ModuleCreator;


/**
 * Abbreviation. For example OR (@0 @1) := NOT(AND(@0 @1)).
 * The left side must have only one operator and the right side
 * couldn't have other pattern variables than the left side.
 *
 * @version $Revision: 1.6 $
 * @author  Michael Meyling
 */
public class Abbreviation extends AbstractArgumentList implements Argument,
        ParagraphCheck {

    /** &quot;left&quot; side of abbreviation */
    final private Formula left;

    /** &quot;left&quot; side of abbreviation */
    final private Formula right;


    /**
     * Constructs an abbreviation.
     *
     * @param   arguments     contains left and right side of definition
     * @throws  ArgumentException    if there are not exactly two
     *          arguments that are instances of {@link Formula} or
     *          if the first argument does not have only pattern variables
     *          as arguments or
     *          if the second argument has other pattern variables than the
     *          first one
     */
    public Abbreviation(Argument[] arguments)
            throws ArgumentException {
        super(arguments);
        if (arguments.length != 2) {
            throw new ArgumentException(
                ParagraphConstants.CODE_CONSTRUCTOR_WRONG_ARGUMENT_NUMBER,
                ModuleCreator.getName(this.getClass())
                + ParagraphConstants.OPERATOR_WITH_TWO_ARGUMENTS);
        }
        if (!(arguments[0] instanceof Formula)) {
            throw new ArgumentException(
                ParagraphConstants.CODE_CONSTRUCTOR_WRONG_ARGUMENT_TYPE,
                ModuleCreator.getName(this.getClass())
                + ParagraphConstants.FIRST_ARGUMENT_TYPE
                + ParagraphConstants.FORMULA,
                arguments[0]);
        }
        if (!(arguments[0] instanceof Formula)) {
            throw new ArgumentException(
                ParagraphConstants.CODE_CONSTRUCTOR_WRONG_ARGUMENT_TYPE,
                ModuleCreator.getName(this.getClass())
                + ParagraphConstants.SECOND_ARGUMENT_TYPE
                + ParagraphConstants.FORMULA,
                arguments[1]);
        }
        this.left = (Formula) arguments[0];
        this.right = (Formula) arguments[1];
        final PatternVariables already = new PatternVariables();

        for (int i = 0; i < left.getArgumentSize(); i++) {
            if (!(left.getArgument(i) instanceof PatternVariable)) {
                throw new ArgumentException(
                    ParagraphConstants.CODE_CONSTRUCTOR_WRONG_ARGUMENT_TYPE,
                    ModuleCreator.getName(this.getClass())
                    + ParagraphConstants.FIRST_ARGUMENT
                    + ParagraphConstants.DIFFERENT_PATTERN_VARIABLES,
                    left.getArgument(i));
            } else {
                final PatternVariable variable
                    = (PatternVariable) left.getArgument(i);
                if (already.contains(variable)) {
                    throw new ArgumentException(
                        ParagraphConstants.CODE_CONSTRUCTOR_WRONG_ARGUMENT_TYPE,
                        ModuleCreator.getName(this.getClass())
                        + ParagraphConstants.FIRST_ARGUMENT
                        + ParagraphConstants.DIFFERENT_PATTERN_VARIABLES,
                        left.getArgument(i));
                } else {
                    already.add(variable);
                }
            }
        }
        if (!left.getPatternVariables().equals(right.getPatternVariables())) {
            throw new ArgumentException(
                ParagraphConstants.CODE_CONSTRUCTOR_ARGUMENT_CHECK_FAILED,
                ModuleCreator.getName(this.getClass())
                + ParagraphConstants.SECOND_ARGUMENT
                + ParagraphConstants.SAME_PATTERN_VARIABLES);
        }

    }


    /**
     * Adds abbreviation to module.
     *
     * @param   module   module
     * @param   label     label of paragraph
     */
    public final void check(final Module module, final String label) {
        module.addAbbreviation(label, this, module);

    }


    /** @inherited */
    public final Argument create(final Argument[] arguments)
            throws ArgumentException {
        return new Abbreviation(arguments);
    }


    /** @inherited */
    public final String toString() {
        return "Abbreviation " + getArgument(0) + " := " + getArgument(1);
    }


}
