// $Id: RuleCreator.java,v 1.9 2004/02/27 16:29:56 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.rule;


import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.meyling.principia.argument.Argument;
import com.meyling.principia.argument.ArgumentConstants;
import com.meyling.principia.argument.ArgumentCreator;
import com.meyling.principia.io.Output;
import com.meyling.principia.io.ParsingException;
import com.meyling.principia.io.ParsingTable;
import com.meyling.principia.io.TextInput;
import com.meyling.principia.logic.basic.BasicCreator;


/**
 * This class provides static methods for reading and
 * writing an {@link Argument}.
 *
 * @version $Revision: 1.9 $
 * @author  Michael Meyling
 */
public final class RuleCreator {

    /** string for {@link LinkReference} */
    public static final String RULE_LINK_REFERENCE
        = "LINK";

    /** string for {@link ModusPonens} */
    public static final String RULE_MODUS_PONENS
        = "MODUSPONENS";

    /** string for {@link AddAxiom} */
    public static final String RULE_ADD_AXIOM
        = "ADDAXIOM";

    /** string for {@link AddAxiom} */
    public static final String RULE_APPLY_AXIOM
        = "APPLYAXIOM";

    /** string for {@link AddSenctence} */
    public static final String RULE_ADD_SENTENCE
        = "ADDSENTENCE";

    /** string for {@link ApplySenctence} */
    public static final String RULE_APPLY_SENTENCE
        = "APPLYSENTENCE";

    /** string for {@link UseAbbreviation} */
    public static final String RULE_USE_ABBREVIATION
        = "USEABBREVIATION";

    /** string for {@link ReverseAbbreviation} */
    public static final String RULE_REVERSE_ABBREVIATION
        = "REVERSEABBREVIATION";

    /** string for {@link ReplacePropositonVariable} */
    public static final String RULE_REPLACE_PROPOSITION_VARIABLE
        = "REPLACEPROP";

    /** string for {@link ReplacePredicate} */
    public static final String RULE_REPLACE_PREDICATE_VARIABLE
        = "REPLACEPREDICATE";

    /** string for {@link RenameFreeSubjectVariable} */
    public static final String RULE_RENAME_FREE_SUBJECT_VARIABLE
        = "RENAMEFREEVARIABLE";

    /** string for {@link RenameBoundSubjectVariable} */
    public static final String RULE_RENAME_BOUND_SUBJECT_VARIABLE
        = "RENAMEBOUNDVARIABLE";

    /** string for {@link Generalization} */
    public static final String RULE_GENERALIZATION
        = "GENERALIZATION";

    /** string for {@link Particularization} */
    public static final String RULE_PARTICULARIZATION
        = "PARTICULARIZATION";

    /** string for {@link HypotheticalSyllogism} */
    public static final String RULE_HYPOTHETICAL_SYLLOGISM
        = "HYPOTHETICALSYLLOGISM";

    /** string for {@link HypotheticalSyllogism} */
    public static final String RULE_SUBST_LINE
        = "SUBSTLINE";

    /** string for {@link RightAddition} */
    public static final String RULE_RIGHT_ADDITION
        = "RIGHTADDITION";

    /** string for {@link ElementaryEquivalence} */
    public static final String RULE_ELEMENTARY_EQUIVALENCE
        = "IMPLICATIONEQUIVALENT";

    /** string for {@link ElementaryEquivalence} */
    public static final String RULE_CONJUNCTION_RULE
        = "CONJUNCTION";

    /** string for {@link LeftAddition} */
    public static final String RULE_LEFT_ADDITION
        = "LEFTADDITION";

    /** string for {@link ReverseImplication} */
    public static final String RULE_REVERSE_IMPLICATION
        = "REVERSEIMPLICATION";

    /** string for {@link LeftAdditionConjunction} */
    public static final String RULE_LEFT_ADDITION_CONJUNCTION
        = "LEFTADDITIONCONJUNCTION";

    /** string for {@link RightAdditionConjunction} */
    public static final String RULE_RIGHT_ADDITION_CONJUNCTION
        = "RIGHTADDITIONCONJUNCTION";

    /** string for {@link RightAdditionImplication} */
    public static final String RULE_LEFT_ADDITION_IMPLICATION
        = "LEFTADDITIONIMPLICATION";

    /** string for {@link RightAdditionImplication} */
    public static final String RULE_RIGHT_ADDITION_IMPLICATION
        = "RIGHTADDITIONIMPLICATION";

    /** string for {@link RightAdditionImplication} */
    public static final String RULE_LEFT_ADDITION_EQUIVALENCE
        = "LEFTADDITIONEQUIVALENCE";

    /** string for {@link RightAdditionImplication} */
    public static final String RULE_RIGHT_ADDITION_EQUIVALENCE
        = "RIGHTADDITIONEQUIVALENCE";


    /**
     * for converting a <code>String</code> into an
     * (Argument) <code>class</code>
     */
    private final static Map string2class = new HashMap();

    /**
     * for converting an (Argument) <code>class</code> into an
     * <code>String</code>
     */
    private final static Map class2string = new HashMap();


    /**
     * Make attribut initialization.
     */
    static {
        // fill hash map
        string2class.put(RULE_LINK_REFERENCE,
                         LinkReference.class);
        string2class.put(RULE_MODUS_PONENS,
                         ModusPonens.class);
        string2class.put(RULE_ADD_AXIOM,
                         AddAxiom.class);
        string2class.put(RULE_APPLY_AXIOM,
                         ApplyAxiom.class);
        string2class.put(RULE_USE_ABBREVIATION,
                         UseAbbreviation.class);
        string2class.put(RULE_REVERSE_ABBREVIATION,
                         ReverseAbbreviation.class);
        string2class.put(RULE_REPLACE_PROPOSITION_VARIABLE,
                         ReplacePropositionVariable.class);
        string2class.put(RULE_REPLACE_PREDICATE_VARIABLE,
                         ReplacePredicateVariable.class);
        string2class.put(RULE_RENAME_FREE_SUBJECT_VARIABLE,
                         RenameFreeSubjectVariable.class);
        string2class.put(RULE_RENAME_BOUND_SUBJECT_VARIABLE,
                         RenameBoundSubjectVariable.class);
        string2class.put(RULE_GENERALIZATION,
                         Generalization.class);
        string2class.put(RULE_PARTICULARIZATION,
                         Particularization.class);
        string2class.put(RULE_ADD_SENTENCE,
                         AddSentence.class);
        string2class.put(RULE_APPLY_SENTENCE,
                         ApplySentence.class);
        string2class.put(RULE_HYPOTHETICAL_SYLLOGISM,
                         HypotheticalSyllogism.class);
        string2class.put(RULE_SUBST_LINE,
                         SubstLine.class);
        string2class.put(RULE_RIGHT_ADDITION,
                         RightAddition.class);
        string2class.put(RULE_ELEMENTARY_EQUIVALENCE,
                         ElementaryEquivalence.class);
        string2class.put(RULE_CONJUNCTION_RULE,
                         ConjunctionRule.class);
        string2class.put(RULE_LEFT_ADDITION,
                         LeftAddition.class);
        string2class.put(RULE_REVERSE_IMPLICATION,
                         ReverseImplication.class);
        string2class.put(RULE_LEFT_ADDITION_CONJUNCTION,
                         LeftAdditionConjunction.class);
        string2class.put(RULE_RIGHT_ADDITION_CONJUNCTION,
                         RightAdditionConjunction.class);
        string2class.put(RULE_LEFT_ADDITION_IMPLICATION,
                         LeftAdditionImplication.class);
        string2class.put(RULE_RIGHT_ADDITION_IMPLICATION,
                         RightAdditionImplication.class);
        string2class.put(RULE_LEFT_ADDITION_EQUIVALENCE,
                         LeftAdditionEquivalence.class);
        string2class.put(RULE_RIGHT_ADDITION_EQUIVALENCE,
                         RightAdditionEquivalence.class);

        // add all the basic staff from package
        //  com.meyling.principia.logic.basic
        string2class.putAll(BasicCreator.getMap());

        // build inverse mapping
        for (Iterator it = string2class.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry entry = (Map.Entry) it.next();
            class2string.put(entry.getValue(), entry.getKey());
        }

    }


    /**
     * Get the mapping of Strings to operator classes. The returned Map
     * should not be modified.
     *
     * @return  mapping of known Strings, do not change this Map
     */
    public final static Map getMap() {
        return string2class;
    }


    /**
     * Get name of known operator class.
     *
     * @param   clazz   look for name of this class
     * @return  name of operator class
     * @throws  IllegalArgumentException    if operator class <code>c</code>
     *          is unknown
     */
    public final static String getName(final Class clazz)
            throws IllegalArgumentException {
        final String result;
        try {
            result = (String) class2string.get(clazz);
        } catch (Exception e) {
            throw new IllegalArgumentException(e.toString());
        }
        if (result == null) {
            throw new IllegalArgumentException(clazz.getName()
                + ArgumentConstants.UNKNOWN_CLASS);
        }
        return result;
    }


    /**
     * Create an {@link Argument} out of an {@link TextInput} object.
     *
     * @param   input   source to read from
     * @param   parsing maps {@link Argument}s into {@link Position}s
     * @return  created argument
     * @throws  ParsingException    if creation failed
     */
    public final static Argument readArgument(final TextInput input,
            final ParsingTable parsing)
            throws ParsingException {
        return ArgumentCreator.readArgument(input, string2class, parsing);
    }


    /**
     * Write an {@link Argument} to an {@link Output} object.
     *
     * @param   output   destination to write to
     * @param   argument this object will be written
     * @throws  IllegalArgumentException    if writing failed
     */
    public final static void writeArgument(final Output output,
            final Argument argument) throws IllegalArgumentException {
        ArgumentCreator.writeArgument(output, argument, class2string);
    }


    /**
     * Write an {@link Argument} to an <code>String</code>.
     *
     * @param   argument this object will be written
     * @return  created string
     * @throws  IllegalArgumentException    if writing failed
     */
    public final static String writeArgument(
            final Argument argument) throws IllegalArgumentException {
        return ArgumentCreator.writeArgument(argument, class2string);
    }


}
