// $Id: PatternVariables.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.argument;


import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;


/**
 * Set of pattern variables.
 *
 * @version $Revision: 1.6 $
 * @author  Michael Meyling
 */
public class PatternVariables {

    /** here is the list */
    private final Map variables;


    /**
     * Construct an empty set of pattern variables.
     */
    public PatternVariables() {
        variables = new TreeMap();
    }


    /**
     * Copy constructor, constructs a new object with the
     * data of another object. There will be made no deep copy of
     * the underlying objects.
     *
     * @param   var     object to copy
     */
    public PatternVariables(final PatternVariables var) {
        variables = var.getMap();
    }


    /**
     * Add an {@link PatternVariable} if not already there.
     *
     * @param   variable    variable to add
     */
    public final void add(final PatternVariable variable) {
        if (!variables.containsKey(variable)) {
            variables.put(variable, variable);
        }
    }


    /**
     * Get {@link PatternVariable} object from the set.
     *
     * @param   variable    the number of this variable determines the
     *                      result
     * @return  object in the set, which has the same number
     * @throws  IllegalArgumentException if such a patter variable was
     *          not found in set
     */
    public final PatternVariable get(final PatternVariable variable)
            throws IllegalArgumentException {
        if (variables.containsKey(variable)) {
            return (PatternVariable) (variables.get(variable));
        } else {
            throw new IllegalArgumentException(
                ArgumentConstants.PATTERN_VARIABLE_NOT_FOUND);
        }
    }


    /**
     * Is <code>variable</code> in the set?
     *
     * @param   variable    check for this variable
     * @return  <code>true</code> iff a variable with such an number is
     *          in the set
     */
    public final boolean contains(final PatternVariable variable) {
        return variables.containsKey(variable);
    }


    /**
     * Are these {@link PatternVariable}s in the set?
     *
     * @param   variables    check for these variables
     * @return  <code>true</code> iff all variables have an counterpart
     *          with same number in the set
     */
    public final boolean contains(final PatternVariables variables) {
        for (Iterator iterator = variables.getMap().entrySet().iterator();
                iterator.hasNext(); ) {
            Map.Entry entry = (Map.Entry) iterator.next();
            if (!this.variables.containsKey(entry.getKey())) {
                return false;
            }
        }
        return true;
    }


    /**
     * Are all of these {@link PatternVariable}s not in the set?
     *
     * @param   variables    check for these variables
     * @return  <code>true</code> iff all variables have no counterpart
     *          with same number in the set
     */
    public final boolean emptyIntersection(final PatternVariables variables) {
        for (Iterator iterator = variables.getMap().entrySet().iterator();
                iterator.hasNext(); ) {
            Map.Entry entry = (Map.Entry) iterator.next();
            if (this.variables.containsKey(entry.getKey())) {
                return false;
            }
        }
        return true;
    }


    /**
     * Is this object equal to another one?
     *
     * @param   variables object to compare with
     * @return  do all their entries are equal?
     */
    public final boolean equals(final PatternVariables variables) {
        if (variables.getMap().size() != this.variables.size()) {
            return false;
        }
        for (Iterator iterator = variables.getMap().entrySet().iterator();
                iterator.hasNext(); ) {
            Map.Entry entry = (Map.Entry) iterator.next();
            if (!this.variables.containsKey(entry.getKey())) {
                return false;
            }
        }
        return true;
    }


    /**
     * Add all these {@link PatternVariable}s to the set?
     *
     * @param   newOnes add these variables
     */
    public final void addAll(final PatternVariables newOnes) {
        for (Iterator iterator = newOnes.getMap().entrySet().iterator();
                iterator.hasNext(); ) {
            Map.Entry entry = (Map.Entry) iterator.next();
            if (!variables.containsKey(entry.getKey())) {
                variables.put(entry.getKey(), entry.getValue());
            }
        }
    }


    /**
     * Get number of elements in the set.
     *
     * @return  number of set elements
     */
    public final int getSize() {
        return variables.size();
    }


    /**
     * Remove pattern variable with same number from the set.
     *
     * @param   variable    pattern variable that should be
     *          removed from the set.
     */
    public final void remove(PatternVariable variable) {
        variables.remove(variable);
    }


    /**
     * Return map of set of pattern variables.
     *
     * @return map of set elements
     */
    public final Map getMap() {
        return variables;
    }


    /**
     * Get a string representation of this object.
     *
     * @return  object description
     */
    public final String toString() {
        final StringBuffer result = new StringBuffer("(");
        boolean notFirst = false;
        for (Iterator iterator = variables.entrySet().iterator();
                iterator.hasNext(); ) {
            Map.Entry entry = (Map.Entry) iterator.next();
            if (notFirst) {
                result.append(", ");
            } else {
                notFirst = true;
            }
            result.append(((PatternVariable) entry.getKey()).toString());
        }
        result.append(")");
        return result.toString();
    }


}
