// $Id: BasicCreator.java,v 1.5 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 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;


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

    /** string for a {@link Conjunction} */
    public static final String CONJUNCTION
        = "AND";

    /** string for a {@link Disjunction} */
    public static final String DISJUNCTION
        = "OR";

    /** string for a {@link Negation} */
    public static final String NEGATION
        = "NOT";

    /** string for an {@link Implication} */
    public static final String IMPLICATION
        = "IMPL";

    /** string for an {@link Equivalence} */
    public static final String EQUIVALENCE
        = "EQUI";

    /** string for a {@link PredicateVariable} */
    public static final String PREDICATE_VARIABLE
        = "PREDVAR";

    /** string for a {@link PropositionVariable} */
    public static final String PROPOSITION_VARIABLE
        = "PROP";

    /** string for a {@link SubjectVariable} */
    public static final String SUBJECT_VARIABLE
        = "VAR";

    /** string for a {@link ExistentialQuantifier} */
    public static final String EXISTENTIAL_QUANTIFIER
        = "EXISTS";

    /** string for a {@link UniversalQuantifier} */
    public static final String UNIVERSAL_QUANTIFIER
        = "FORALL";

    /** string for a {@link RegularArgumentList} */
    public static final String REGULAR_ARGUMENT_LIST
        = "L";

    /** string for a {@link FormulaPatternVariable} */
    public static final String BASIC_FORMULA_PATTERN_VARIABLE
        = "FPATTERN";

    /** string for a {@link SubjectVariablePatternVariable} */
    public static final String BASIC_SUBJECT_VARIABLE_PATTERN_VARIABLE
        = "SPATTERN";

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

    /**
     * for converting a (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(CONJUNCTION,           Conjunction.class);
        string2class.put(DISJUNCTION,           Disjunction.class);
        string2class.put(NEGATION,              Negation.class);
        string2class.put(IMPLICATION,           Implication.class);
        string2class.put(EQUIVALENCE,           Equivalence.class);
        string2class.put(PREDICATE_VARIABLE,    PredicateVariable.class);
        string2class.put(PROPOSITION_VARIABLE,  PropositionVariable.class);
        string2class.put(SUBJECT_VARIABLE,      SubjectVariable.class);
        string2class.put(EXISTENTIAL_QUANTIFIER, ExistentialQuantifier.class);
        string2class.put(UNIVERSAL_QUANTIFIER,  UniversalQuantifier.class);
        string2class.put(REGULAR_ARGUMENT_LIST, RegularArgumentList.class);
        string2class.put(BASIC_FORMULA_PATTERN_VARIABLE,
                 BasicFormulaPatternVariable.class);
        string2class.put(BASIC_SUBJECT_VARIABLE_PATTERN_VARIABLE,
                 BasicSubjectVariablePatternVariable.class);

        // 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);
    }


}
