/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: tt_struct.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: hr $ $Date: 2006/06/19 13:08:49 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/

#ifndef UDM_TT_STRUCT_HXX
#define UDM_TT_STRUCT_HXX


// USED SERVICES
	// BASE CLASSES
#include <udm/type_traits.hxx>
	// COMPONENTS
	// PARAMETERS
#include <cosv/template/tpltools.hxx>
#include <udm/i_struct.hxx>
#include <udm/keyset.hxx>



namespace udm
{

//**********************        MemberInfo          ***************//
template <class SRC>
class MemberInfo
{
  public:
    virtual             ~MemberInfo() {}

    DYN Data &          create_data_for(
                            const SRC &         i_rObj ) const;
  private:
    virtual DYN Data &  do_CreateDataFor(
                            const SRC &         i_rObj ) const = 0;
};

template <class SRC>
inline DYN Data &
MemberInfo<SRC>::create_data_for( const SRC & i_rSrc ) const
{ return do_CreateDataFor(i_rSrc); }




//**********************        struct_traits         ***************//


template <class> class KeySet;

template <class SRC>
class struct_traits : public type_traits<SRC>
{
  public:
    typedef SRC     source_type;

                        ~struct_traits();

    // OPERATIONS
    DYN Data &          create_member_data_for(
                            member_id           i_m,
                            const SRC &         i_rSrc ) const;
    // INQUIRY
    member_id           count_members() const   { return aMembers.size(); }
    const KeySet<SRC> * get_keyset() const      { return pKeysForThisType; }

    // ACCESS
    void                reserve(
                            size_t              i_nSize )
                                                { aMembers.reserve(i_nSize); }
    void                add_member(
                            DYN MemberInfo<SRC> &
                                                let_drInfo )
                                                { aMembers.push_back( &let_drInfo ); }
    void                set_keyset(
                            const KeySet<SRC> * i_pKeysForThisType );
  private:
    typedef std::vector< DYN MemberInfo<SRC> * > List_MemberInfos;
    typedef void (*F_SCHEME_CREATE)( struct_traits<SRC> & );

    friend DYN type_traits<SRC> &
                        create_traits<SRC>( csv::Type2Type<SRC> );

                        struct_traits(
                            F_SCHEME_CREATE     i_fSchemeCreator,
                            const KeySet<SRC> * i_pKeysForThisType = 0 );

    virtual DYN Data &  do_CreateData() const;
    virtual void        do_ConnectOriginal(
                            Data &              o_rData,
                            const SRC &         i_rOriginal ) const;
    virtual DYN SRC *   do_CreateObject() const;

/*
    virtual member_id   inq_MaxMemberId() const;

    virtual Data::description
                        inq_TypeDescription() const;
*/
    // DATA
    List_MemberInfos    aMembers;
    const KeySet<SRC> * pKeysForThisType;
};

template <class SRC>
struct_traits<SRC>::struct_traits( F_SCHEME_CREATE      i_fSchemeCreator,
                                   const KeySet<SRC> *  i_pKeysForThisType )
    :   aMembers(),
        pKeysForThisType(i_pKeysForThisType)
{
    (*i_fSchemeCreator)( *this );
}

template <class SRC>
struct_traits<SRC>::~struct_traits()
{
    csv::erase_container_of_heap_ptrs(aMembers);
}

template <class SRC>
DYN Data &
struct_traits<SRC>::create_member_data_for( member_id   i_m,
                                            const SRC & i_rSrc ) const
{
    csv_assert(i_m < aMembers.size());
    return aMembers[i_m]->create_data_for( i_rSrc );
}

template <class SRC>
inline void
struct_traits<SRC>::set_keyset( const KeySet<SRC> * i_pKeysForThisType )
{
    pKeysForThisType = i_pKeysForThisType;
}

template <class SRC>
DYN Data &
struct_traits<SRC>::do_CreateData() const
{
    return * new TStruct<SRC>( aMembers.size() );
}

template <class SRC>
void
struct_traits<SRC>::do_ConnectOriginal( Data &      o_rData,
                                        const SRC & io_rOriginal ) const
{
    static_cast< TStruct<SRC> & >(o_rData).connect_to(io_rOriginal);
}

template <class SRC>
DYN SRC *
struct_traits<SRC>::do_CreateObject() const
{
    return new SRC();
}



//**********************        TMemberInfo         ***************//


template <class SRC, class MEMBER_TYPE>
class TMemberInfo : public MemberInfo<SRC>
{
  public:
    typedef MEMBER_TYPE SRC::* ptr2member;

                        TMemberInfo(
                            ptr2member          i_mpOriginalData );
                        ~TMemberInfo();

  private:
    virtual DYN Data &  do_CreateDataFor(
                            const SRC &         i_rSrc ) const;
    // DATA
    ptr2member          mpOriginalData;
};

#if 0   // because of gcc 2.95
        // That works, because this code is currently unused.
template <class SRC, class MEMBER_TYPE>
TMemberInfo<SRC,MEMBER_TYPE>::TMemberInfo( ptr2member i_mpOriginalData )
    :   mpOriginalData(i_mpOriginalData)
{
}
#endif // 0

template <class SRC, class MEMBER_TYPE>
TMemberInfo<SRC,MEMBER_TYPE>::~TMemberInfo()
{
}

template <class SRC, class MEMBER_TYPE>
DYN Data &
TMemberInfo<SRC,MEMBER_TYPE>::do_CreateDataFor( const SRC & i_rSrc ) const
{
    return type_traits<MEMBER_TYPE>::get_()
                .create_data_for( i_rSrc.*mpOriginalData );
}



//*************        add_traits_member()        ***************//
template <class STRUCT_TYPE, class MEMBER_TYPE>
inline void
add_traits_member( struct_traits<STRUCT_TYPE> & r_out,
                   MEMBER_TYPE STRUCT_TYPE::*   i_pMember )
{
    r_out.add_member( *new TMemberInfo<STRUCT_TYPE,MEMBER_TYPE>(i_pMember) );
}


}   // namespace udm



#endif


