/*!
  @file           SAPDBFields_FieldMap.hpp
  @author         StefanB,TillW,UweH
  @ingroup        Field Container classes
  @brief          Declarations for class SAPDBFields_FieldMap

\if EMIT_LICENCE
    ========== licence begin  GPL
    Copyright (c) 2000-2005 SAP AG

    This program 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.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end

\endif
*/


#ifndef SAPDBFields_FieldMap_HPP
#define SAPDBFields_FieldMap_HPP


#include "SAPDBCommon/Fields/SAPDBFields_IFieldSequences.hpp"
#include "Container/Container_Vector.hpp"

/*!
@class          SAPDBFields_FieldMap
@brief          A map of (index,field) entries with fields scattered in memory.
*/

class SAPDBFields_FieldMap : public SAPDBFields_IFieldSequence
{
public:
    /*!
       @brief  Constructs a field map with a amximum of &lt;N> elements.
       @param  RawAllocator [in] The underlying raw allocator, where the entries are located.
               Note, that only the handler to the fields are located in the
               memory of the raw allocator, not the fields themself.
       @param  Max [in] The maximum number of entries in the field map. The actual 
               size of the field map depends at which positions entries have
               been filled into the field map.
       @example
       SAPDBFields_FieldMap MyMap(Alloc, 10);
       // Now the size of MyMap is zero.
       MyMap.Fill(7, 10, field);
       // The size now is 8. ATTENTION! Fields number 0 through 6
       // are not assigned at this stage.
       MyMap.Fill(10, 17, field); // not possible

        The map initially contains no field handler.
        To fill fields into the map the method 'Fill()' must be used
    */
    SAPDBFields_FieldMap ( SAPDBMem_IRawAllocator& allocator,
                           IndexType               max);

    virtual IndexType GetFieldCount() const
    {
        return m_Content.GetSize();
	}

    virtual SAPDBFields_Field& GetField( IndexType          N,
                                         SAPDBFields_Field &Field ) const
    {
        SAPDBERR_ASSERT_ARGUMENT(N < GetFieldCount());
        Field = m_Content[N].Field;
        return Field;
    }

    virtual SAPDBFields_Field::SizeType GetFieldLength(IndexType N) const
    {
        return m_Content[N].Field.GetLength();
    }

    virtual SAPDBFields_Field::SizeType GetTotalLength() const;

    virtual SAPDBFields_Field::SizeType Write(SAPDBFields_Field            &Destination, 
                                              SAPDBFields_Field::IndexType  Offset,
                                              IndexType                     Begin, 
                                              IndexType                     End) const;

    virtual IndexType GetIndex(IndexType N)
    {
        SAPDBERR_ASSERT_ARGUMENT(N < GetFieldCount());
        return m_Content[N].Index;
    }

    virtual void Fill(IndexType Pos, IndexType  Index,
                      const SAPDBFields_Field  &Field);

    /// Sorts the map by the index (ascending).
    void Sort();

protected:

    virtual void Print(SAPDB_OStream& os) const;

private:

    struct EntryType
	{
        IndexType         Index;
        SAPDBFields_Field Field;
        EntryType()
        : Index(0)
        {}
        EntryType(IndexType I, const SAPDBFields_Field& F)
        : Index(I),
          Field(F)
        {}
        bool operator==(const EntryType& E) const
        {
            return (Index == E.Index) && (Field == E.Field);
        }
    };
    typedef Container_Vector<EntryType> VectorType;

    /// The content of the field map
    VectorType m_Content;
};



#endif // SAPDBFields_FieldMap_HPP

