// -*- c++ -*-

/*
 * Jakelib2 - General purpose C++ library
 * Copyright (C) 2001 Florian Wolff  (florian@donuz.de)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * $Id: AbstractSet.h,v 1.3 2003/02/18 17:01:19 alfa Exp $
 */

#ifndef INCLUDE_JAKELIB2_UTIL_ABSTRACTSET_H
# define INCLUDE_JAKELIB2_UTIL_ABSTRACTSET_H

#include "AbstractCollection.h"
#include "Set.h"

namespace jakelib {
  namespace util {
    class Iterator;

    /**
     * An abstract implementation of Set to make it easier to create your own
     * implementations. In order to create a Set, subclass AbstractSet and
     * implement the same methods that are required for AbstractCollection
     * (although these methods must of course meet the requirements that Set puts
     * on them - specifically, no element may be in the set more than once). This
     * class simply provides implementations of equals() and hashCode() to fulfil
     * the requirements placed on them by the Set interface.
     *
     * @author Original author unknown
     * @author Eric Blake <ebb9@email.byu.edu>
     * @see Collection
     * @see AbstractCollection
     * @see Set
     * @see HashSet
     * @see TreeSet
     * @see LinkedHashSet
     * @since 1.2
     * @status updated to 1.4
     */

    class AbstractSet : public jakelib::util::AbstractCollection, virtual public jakelib::util::Set
    {
      /**
       * The main constructor, for use by subclasses.
       */
    protected: AbstractSet();

      /**
       * Tests whether the given object is equal to this Set. This implementation
       * first checks whether this set <em>is</em> the given object, and returns
       * true if so. Otherwise, if o is a Set and is the same size as this one, it
       * returns the result of calling containsAll on the given Set. Otherwise, it
       * returns false.
       *
       * @param o the Object to be tested for equality with this Set
       * @return true if the given object is equal to this Set
       */
    public: virtual jboolean equals(jakelib::lang::Object* o);

      /**
       * Returns a hash code for this Set. The hash code of a Set is the sum of the
       * hash codes of all its elements, except that the hash code of null is
       * defined to be zero. This implementation obtains an Iterator over the Set,
       * and sums the results.
       *
       * @return a hash code for this Set
       */
    public: virtual jint hashCode();

      /**
       * Removes from this set all elements in the given collection (optional
       * operation). This implementation uses <code>size()</code> to determine
       * the smaller collection.  Then, if this set is smaller, it iterates
       * over the set, calling Iterator.remove if the collection contains
       * the element.  If this set is larger, it iterates over the collection,
       * calling Set.remove for all elements in the collection. Note that
       * this operation will fail if a remove methods is not supported.
       *
       * @param c the collection of elements to remove
       * @return true if the set was modified as a result
       * @throws UnsupportedOperationException if remove is not supported
       * @throws NullPointerException if the collection is null
       * @see AbstractCollection#remove(Object)
       * @see Collection#contains(Object)
       * @see Iterator#remove()
       */
    public: virtual jboolean removeAll(Collection* c);

      /**
       * @brief Returns the number of elements in the set. If there are more
       * than Integer.MAX_VALUE mappings, return Integer.MAX_VALUE. This is
       * the <i>cardinality</i> of the set.
       * 
       * @return the number of elements
       */
    public: virtual int size() = 0;

      /**
       * @brief Returns true if this set contains all elements in the specified
       * collection. If the argument is also a set, this is the <i>subset</i>
       * relationship.
       *
       * @param c the collection to check membership in
       * @return \c true if all elements in this set are in c
       * @throws NullPointerException if c is null
       * @see #contains(Object)
       */
    public: virtual jboolean containsAll(jakelib::util::Collection* c) = 0;

      /**
       * @brief Returns an iterator over the set.  The iterator has no specific order,
       * unless further specified.
       *
       * @return a set iterator
       */
    public: virtual jakelib::util::Iterator* iterator() = 0;

      /**
       * @brief Removes the specified element from this set (optional operation). If
       * an element e exists, <code>o == null ? e == null : o.equals(e)</code>,
       * it is removed from the set.
       *
       * @param o the object to remove
       * @return \c true if the set changed (an object was removed)
       * @throws UnsupportedOperationException if this operation is not allowed
       */
    public: virtual jboolean remove(jakelib::lang::Object* o) = 0;

      JAKELIB_DECLARE_CLASS(AbstractSet);
    };

 
  }
}
#endif
