// -*- 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: Vector.h,v 1.23 2003/08/28 16:55:20 florian Exp $
 */

#ifndef INCLUDE_JAKELIB2_UTIL_VECTOR_H
# define INCLUDE_JAKELIB2_UTIL_VECTOR_H
# include "../lang/Synchronizeable.h"

namespace jakelib {
  namespace util {

    /**
     * \c Vector is a synchronized self-growing array.
     *
     * @class Vector
     * @version $Id: Vector.h,v 1.23 2003/08/28 16:55:20 florian Exp $
     * @author Florian 'Overflo' Wolff (florian@donuz.de)
     */
    class Vector : public jakelib::lang::Object,
                   public jakelib::lang::Synchronizeable
      {
      public:
	/**
	 * @brief Constructs an empty vector so that its internal data array
	 * has size \c 10 and its standard capacity increment is
	 * zero.
	 */
	Vector();
  
	/**
	 * @brief Constructs an empty vector with the specified initial capacity and
	 * with its capacity increment equal to zero.
	 *
	 * @param initialCapacity The initial capacity of the vector.
	 * @exception IllegalArgumentException If the specified initial capacity is negative
	 */
	Vector(int initialCapacity);
  
	/**
	 * @brief Constructs an empty vector with the specified initial capacity and
	 * capacity increment. 
	 *
	 * @param initialCapacity The initial capacity of the vector.
	 * @param capacityIncrement The amount by which the capacity is increased when the vector overflows.
	 * @exception IllegalArgumentException If the specified initial capacity is negative
	 */
	Vector(int initialCapacity, int capacityIncrement);
  
	~Vector();
  
	/**
	 * @brief Appends the specified element to the end of this Vector.
	 *
	 * @param object element to be appended to this Vector.
	 * @return Index of new entry.
	 */
	int addElement(jakelib::lang::Object* object);
  
	jakelib::lang::Object* elementAt(int index);
  
	int size();
  
	jboolean isEmpty();
  
	void flush() {}; //+++AlFa where is the implementation of this function ???
  
	void set(int index, jakelib::lang::Object* object);
  
	void clear();
  
	int indexOf(jakelib::lang::Object* object);
  
	jboolean contains(jakelib::lang::Object* object);
  
	void removeLastElement();
  
	void removeElementAt(int index);

	jboolean removeElement(jakelib::lang::Object* object);

        /**
         * @brief Returns a string representation of this \c Vector.
         */
        jakelib::lang::String* toString();
        /**
         * Copies the contents of a provided array into the Vector.  If the
         * array is too large to fit in the Vector, an IndexOutOfBoundsException
         * is thrown without modifying the array.  Old elements in the Vector are
         * overwritten by the new elements.
         *
         * @param a target array for the copy
         * @throws IndexOutOfBoundsException the array is not large enough
         * @throws NullPointerException the array is null
         * @see #toArray(Object[])
         */
        void copyInto(jakelib::lang::Array* a);
     
        /**
         * Explicitly sets the size of the vector (but not necessarily the size of
         * the internal data array). If the new size is smaller than the old one,
         * old values that don't fit are lost. If the new size is larger than the
         * old one, the vector is padded with null entries.
         *
         * @param newSize The new size of the internal array
         * @throws ArrayIndexOutOfBoundsException if the new size is negative
         */
        void setSize(jint newSize);
      
        /**
         * Changes the element at <code>index</code> to be <code>obj</code>
         *
         * @param obj the object to store
         * @param index the position in the Vector to store the object
         * @throws ArrayIndexOutOfBoundsException the index is out of range
         * @see #set(int, Object)
         */
        void setElementAt(jakelib::lang::Object* obj, jint index);

      protected:

	jakelib::lang::Object** elementData;
  
	int elementCount;
  
	int capacityIncrement;
  
	int capacity;

	void init(int initialCapacity, int capacityIncrement);

	void ensureCapacity(int minCapacity);
  
	JAKELIB_DECLARE_CLASS(Vector);
      };

  }
}
#endif

