#ifndef _ISEQ2_
  #define _ISEQ2_
/*******************************************************************************
*                                                                              *
* COPYRIGHT:                                                                   *
*   IBM Open Class Library                                                     *
*   (C) Copyright International Business Machines Corporation 1992, 1997       *
*   Licensed Material - Program-Property of IBM - All Rights Reserved.         *
*                                                                              *
*******************************************************************************/
#include <ibase.hpp>

#ifdef IC_USE_STL

  #include <istdops2.h>

  #define __USE_MALLOC
  #include <list.h>
  template <class Element, class Imp>
  class ITImpSequence
  {
  public:
     ITImpSequence (unsigned long numberOfElements = 100);
    ~ITImpSequence ();
     class Cursor
     {
     public:
       Cursor (const ITImpSequence<Element, Imp>& aList)
         : fList((ITImpSequence<Element, Imp>&)aList),
           fIterator(fList.fImp.begin()) {}
       // Note: We should really be storing a const reference to the
       //       container and using a const iterator but this causes
       //       grief when trying to replace the iterator in
       //       functions like:
       //         ISequence::addAsNext(const Element& t, Cursor& cursor)
       Cursor ( const Cursor& cursor)
         : fList(cursor.fList),
           fIterator(cursor.fIterator)   {}

       Cursor& operator=(const Cursor& cursor)
       {
         if(this != &cursor)
         {
            fList = cursor.fList;
            fIterator = cursor.fIterator;
         }
         return *this;
       }

       bool setToFirst ()
            { fIterator = fList.fImp.begin();
              return fList.fImp.empty();}
       bool setToLast ()
            { fIterator = fList.fImp.end();   fIterator--;
              return fList.fImp.empty();}
       bool setToNext ()
            { fIterator++;
              return fList.fImp.empty();}
       bool setToPrevious ()
            { fIterator--;
              return fList.fImp.empty();}
       bool isValid() const
            { return (fList.fImp.begin()!=fList.fImp.end()
                     && fIterator!=fList.fImp.end()); }
       void invalidate ( )
       {     fIterator = fList.fImp.end(); }

       Element const
        &element    ( ) const
            { return (Element const&)*fIterator;   }

       private:
         ITImpSequence<Element, Imp>
          &fList;
         list<Imp>::iterator
           fIterator;
        friend class ITImpSequence<Element, Imp>;
     }; // Cursor


     bool
       add       ( const Element& element)
             { fImp.push_back((const Imp&)element); return true;}

     void
       addAllFrom ( const ITImpSequence<Element, Imp>& collection)
       {
          list<Imp>::const_iterator old = collection.fImp.begin();
          while(old!=collection.fImp.end())
          {
             fImp.push_back((const Imp&)*old);
             old++;
          }
       }

     bool
       addAsLast ( const Element& element)
             { fImp.push_back((const Imp&)element); return true;}

     bool
       addAsFirst ( const Element& element)
             { fImp.push_front((const Imp&)element); return true;}

     bool
       addAsNext  ( const Element& element, Cursor& cursor)
       {  // double-check logic
          cursor.fIterator++;
          cursor.fIterator = fImp.insert( cursor.fIterator, element);
          return true;
       }
     bool // double-check logic
       addAtPosition ( unsigned long pos, const Element& element)
       {
          list<Imp>::iterator addIterator = fImp.begin();
          unsigned long currentPos = 1;
          while(addIterator != fImp.end() && currentPos < pos)
          {
             currentPos++;
             addIterator++;
          }
          fImp.insert( addIterator, element);
          return true;
       }

     bool  // double-check logic
       addAsPrevious  ( const Element& element, Cursor& cursor)
       {
          cursor.fIterator = fImp.insert( cursor.fIterator, element);
          return true;
       }

     bool
       allElementsDo   ( bool (*function) (Element&, void*),
                         void* additionalArgument = 0)
     {
       list<Imp>::iterator allIterator = fImp.begin();
       bool quit = false;
       while(allIterator != fImp.end() && quit == false)
       {
          quit = function((Element&)*allIterator, additionalArgument);
          allIterator++;
       }
       return !quit;
     }

     bool
       allElementsDo   ( bool (*function) (Element const&, void*),
                         void* additionalArgument = 0) const
        {
          list<Imp>::const_iterator allIterator = fImp.begin();
          bool quit = false;
          while(allIterator != fImp.end() && quit == false)
          {
             quit = function((Element const&)*allIterator, additionalArgument);
             allIterator++;
          }
          return !quit;
        }

     long
       compare ( ITImpSequence<Element, Imp> const& collection,
                 long (*compFunction)(Element const&, Element const&)) const
       {
         long result = 0;

         if (this != &collection) {
           list<Imp>::const_iterator thisIterator = fImp.begin();
           list<Imp>::const_iterator thatIterator = collection.fImp.begin();

           while(thisIterator!=fImp.end() &&
                 thatIterator!=collection.fImp.end() &&
                 result == 0)
           {
              result = (*compFunction) ((Element const&)*thisIterator,
                                    (Element const&)*thatIterator);
              thisIterator++;
              thatIterator++;
           }

           if (result == 0) {

             if (thisIterator != fImp.end() && thatIterator == collection.fImp.end())
               result = 1;
             if (thisIterator == fImp.end() && thatIterator != collection.fImp.end())
               result = -1;
           }
         }
         return result;
       }

     bool
       contains ( Element const& element) const
       {

         list<Imp>::const_iterator first = fImp.begin();
         list<Imp>::const_iterator last  = fImp.end();
         while (first != last && *first != element)
            ++first;
         return (first != fImp.end());
       }

     Element const&
       elementAt   ( const Cursor& cursor) const
        { return (Element const&)*(cursor.fIterator); }

     Element&
       elementAt   ( const Cursor& cursor)
        { return (Element &)*(cursor.fIterator); }

     const Element
      &elementAtPosition ( unsigned long position) const
       {  // Not a cheap thing to do with a list (but probably
          // not worse then the IOC linked list implementation)
          list<Imp>::const_iterator posIterator = fImp.begin();
          for(int i=1; i<position && posIterator != fImp.end(); i++)
          {
            posIterator++;
          }
          return (Element const&)*posIterator;  // May be past the end??
       }

     const Element
      &firstElement       ( ) const
       { return (Element const&)*(fImp.begin()); }

     const Element
      &lastElement       ( ) const
     {
       list<Imp>::const_iterator lastIterator = fImp.end();
       lastIterator--;
       return (Element const&)*lastIterator;
     }

     bool
       // The following is a const function in IOC
       locate ( const Element& element, Cursor& cursor) // const
       {
          list<Imp>::iterator findIterator = fImp.begin();
          bool found = false;
          while(!found && findIterator!=fImp.end())
          {
             if(*findIterator == element)
             {
               found = true;
               cursor.fIterator = findIterator;
             }
             else
                findIterator++;
          }
          return found;
       }

     bool
       isEmpty ( ) const { return (fImp.size() == 0); }

     unsigned long
       position ( Cursor const& cursor ) const
       {
         unsigned long pos = 0;
         list<Imp>::const_iterator cursorIterator = cursor.fIterator;
         while(cursorIterator!=fImp.end())
         {
            pos++;
            cursorIterator++;
         }
         return pos;
       }

     unsigned long
       numberOfElements ( ) const { return fImp.size(); }

     unsigned long
       removeAll ( )
       {
         unsigned long count = fImp.size();
         fImp.erase(fImp.begin(), fImp.end());
         return count;
       }

     unsigned long
       removeAll ( bool (*predicateFunction)(Element const&, void*), void* data=0)
       {
          list<Imp>::iterator posIterator = fImp.begin();
          unsigned long count = 0;
          while(posIterator != fImp.end())
          {
             if(predicateFunction((Element&)*posIterator, data))
             {
               fImp.erase(posIterator);
               count++;
             }
             posIterator++;
          }
          return count;
       }

     void
       removeAt ( Cursor& cursor) { fImp.erase( cursor.fIterator++); }

     void
       removeAtPosition   ( unsigned long position)
       {  // Not a cheap thing to do with a list (but probably
          // not worse then the IOC linked list implementation)
          list<Imp>::iterator posIterator = fImp.begin();
          for(int i=1; i<=position && posIterator != fImp.end(); i++)
          {
            posIterator++;
          }
          fImp.erase(posIterator);  // May be past the end??
       }

     void
       removeFirst ( )
       {
         fImp.erase(fImp.begin());
       }

     void
       removeLast ( )
       {
          list<Imp>::iterator posIterator = fImp.end();
          posIterator--;
          if(posIterator!=fImp.begin())
             fImp.erase(posIterator);
       }

     void // double-check logic
       replaceAt ( const Cursor& cursor, const Element& element)
       {
         list<Imp>::iterator repIterator = cursor.fIterator;
         fImp.insert( cursor.fIterator, element);
         fImp.erase(repIterator);
       }
     void
       // Note: the following should be a const function
       setToPosition ( unsigned long pos, Cursor& cursor) // const
       {
         unsigned long currentPos = 1;
         cursor.fIterator = fImp.begin();
         while(cursor.fIterator != fImp.end() && currentPos < pos)
         {
            cursor.fIterator++;
            currentPos++;
         }
       }

     void
       sort ( long (*comparisonFunction)
           (Element const& element1, Element const& element2))
       {
          class ComparisonFunction {
          public:

          typedef long (*CompareFn)(Element const& element1, Element const& element2);

             ComparisonFunction ( CompareFn comparisonFunction)
               : fCompareFn(comparisonFunction) {}

             bool
               operator()(const Element& element1, const Element& element2) const
                  { return (fCompareFn(element1, element2)>0);}
          private:
          CompareFn
            fCompareFn;
          };
// Note: The following requires support for template member functions.
          // fImp.sort(ComparisonFunction(comparisonFunction));
       }

    private:
  list<Imp>
    fImp;
  friend class Cursor;
  unsigned long
    fNumberOfElements;
  };



template <class Element>
  class ISequence : public ITImpSequence<Element, Element>
{
  public:
     ISequence (unsigned long numberOfElements = 100);
    ~ISequence ();
};

// Collection of Pointers as collection of void*

#ifdef IC_USE_STL_VPTR
  template <class Element>
    class IVPtrSequence : public ITImpSequence<Element, void*>
  {
    public:
       IVPtrSequence (unsigned long numberOfElements = 100);
      ~IVPtrSequence ();
  };
#else
  #define IVPtrSequence ISequence
#endif


// Visual Builder Sequence
template <class Element>
  class IVSequence : public ITImpSequence<Element, Element>
{
  public:
     IVSequence (unsigned long numberOfElements = 100);
    ~IVSequence ();
};


#ifndef __TEMPINC__
  #include <iseq2.c>
#endif



#else // Not STL
  #include <iseq.h>
  #define IVPtrSequence ISequence
#endif

#endif  // _ISEQ2_

