/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: data.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005/09/09 14:22:41 $
 *
 *  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_DATA_HXX
#define UDM_DATA_HXX



// USED SERVICES
	// BASE CLASSES
	// COMPONENTS
	// PARAMETERS
#include <cosv/template/tplutil.hxx>


/** Concept:

    An interface which provides a uniform way to access data in
    an XML-inspired, tree-like structure.

    Allows accessing a specific data element of an object with expressions
    like:

    udm::Data   x( ary::cpp::Class & rClass);
    String sName = x[M_NAME];
    String sFunction = x[M_FUNCTIONS]["Hello"][2][M_NAME];

    Provided Types
    --------------

    Basic 'builtin' types:

        udm::Stdstr            r_str()
        udm::Integer           r_int()
        udm::UInteger          r_uint()
        udm::Real              r_real()
        udm::Boolean           r_bool()
        udm::BinaryStream      r_bstream()

    Adapted 'builtin' types:

        udm::Enum              r_enum()          .v_int() .v_str()
        udm::Ptr               r_ptr()           .r_all()
        udm::Dynamic           r_dyn()           .r_all()

    Metatypes:

        udm::Struct            r_struct()        .r_all()
        udm::Array             r_array()         .r_all()
        udm::Map               r_map()           .r_all()

    Each of these types is just an interface, whose derivation can be a
    specialized read- oder readwrite-mapping to a concrete type or a
    concrete type itself.

    Examples for read-access to members of an udm::Struct object
    ------------------------------------------------------------

    There may be an udm::Struct object, which those members:

    Struct Type1
    {
        udm::Stdstr     m1;     // M_NAME
        udm::Boolean    m2;     // M_VALID
        udm::Enum       m3;     // M_STATE
        udm::Dynamic    m4;     // M_IMPL
        udm::Struct     m5;     // M_SOMEDATA
        udm::Array      m6;     // M_List
        udm::Map        m7;     // M_Dict
    };

    udm::Struct sX(Type1);

    String  sName           =   sX.str_val(1);

    bool    bValid          =   sX.bool_val(2);
    intt    nState          =   sX.enum_ref(3).int_val();
    String  sState          =   sX.enum_ref(3).str_val();

    udm::Struct & rStruct1  =   sX.dyn_ref(4).struct_ref(),
    udm::Struct & rStruct2  =   sX.struct_ref(5);

    udm::Array & rList      =   sX.arrayv(6);        // intt-List
    udm::Map & rMap         =   sX.mapv(7);          // string->struct-Map


    udm::Struct & rStruct1  =   rDyn.structv();
    intt nElem2             =   rList.int_v(2);
    udm::Struct & rStruct4  =   rMap.structv("Hello");


    Intended mode of use
    --------------------

    ObjType     aObj;
    udm::Struct aX( aObj );
    do_anything_with(aX);
*/

namespace csv
{
    class bostream;
    class bistream;
}

namespace udm
{

class Stdstr;
class Integer;
class UInteger;
class Real;
class Boolean;
class BinaryStream;
class Enum;
class Ptr;
class Dynamic;
class Array;
class Map;
class Struct;

class Object;
typedef UINT8 member_id;


class Data 
{
  public:
    enum accessor_type
    {
        t_None      =    0,
        t_String    =    1,
        t_Integer   =    2,
        t_UInteger  =    3,
        t_Real      =    4,
        t_Bool      =    5,
        t_Enum      =    6,
        t_BStream   =    7,
        t_Ptr       =    8,
        t_Dynamic   =    9,
        t_Array     =   10,
        t_Map       =   11,
        t_Struct    =   12
    };

    enum E_RefCount
    {
        free = 0,
        used
    };

    typedef ::csv::String description;        /// This may change - therefore typedefed.

    // LIFECYCLE
    virtual             ~Data() {}
    void                dispose()               { do_Dispose(); }

    // INQUIRY
    accessor_type       type() const;
    /** @return
        TODO
    */
    description         type_description() const;
    /** @return
        If true, this object will return null-types on all
        requests and all assignments will disappear in nowhere.
    */
    bool                is_null() const;

    // ACCESS
    Stdstr &            as_str();
    Integer &           as_int();
    UInteger &          as_uint();
    Real &              as_real();
    Boolean &           as_bool();

    BinaryStream &      as_bstream();
    Enum &              as_enum();
    Ptr &               as_ptr();
    Dynamic &           as_dyn();
    Array &             as_array();
    Map &               as_map();
    Struct &            as_struct();

    /** @return
        A non mutating object (whatever you do with it),
        with is_null() == true.
    */
    static Data &       null_();

  protected:
                        Data();
                        Data( csv::Type2Type<bool> ); // For NullData only.
  private:
    // BEGIN INTERFACE - for class Object only:
    friend class Object;
    void                acquire() const;
    E_RefCount          release() const;

    void                bin_write(
                            csv::bostream &     o_out ) const;
    void                xml_write(
                            csv::bostream &     o_out ) const;
    // END INTERFACE.

    // Forbidden:
                        Data(const Data&);
    Data &              operator=(const Data&);

    // Virtual implementations:
    virtual void        do_Dispose() = 0;
    virtual void        do_BinWrite(
                            csv::bostream &     o_out ) const = 0;
    virtual accessor_type
                        inq_Type() const = 0;
    virtual description inq_TypeDescription() const = 0;
    virtual Stdstr &    access_Str();
    virtual Integer &   access_Int();
    virtual UInteger &  access_Uint();
    virtual Real &      access_Real();
    virtual Boolean &   access_Bool();
    virtual BinaryStream &
                        access_Bstream();
    virtual Enum &      access_Enum();
    virtual Ptr &       access_Ptr();
    virtual Dynamic &   access_Dyn();
    virtual Array &     access_Array();
    virtual Map &       access_Map();
    virtual Struct &    access_Struct();

    // DATA
    mutable unsigned int
                        nRefCount;
};


template <class NULLDATA>
NULLDATA &          get_null( csv::Type2Type<NULLDATA> );



// IMPLEMENTATION

inline
Data::Data()
    : nRefCount(0) {}
inline
Data::Data( csv::Type2Type<bool> )
    : nRefCount(1) {}
inline Data::accessor_type
Data::type() const
    { return inq_Type(); }
inline Data::description
Data::type_description() const
    { return inq_TypeDescription(); }
inline bool
Data::is_null() const
    { return inq_Type() == t_None; }

inline Stdstr &
Data::as_str()
    { return access_Str(); }
inline Integer &
Data::as_int()
    { return access_Int(); }
inline UInteger &
Data::as_uint()
    { return access_Uint(); }
inline Real &
Data::as_real()
    { return access_Real(); }
inline Boolean &
Data::as_bool()
    { return access_Bool(); }
inline BinaryStream &
Data::as_bstream()
    { return access_Bstream(); }
inline Enum &
Data::as_enum()
    { return access_Enum(); }
inline Ptr &
Data::as_ptr()
    { return access_Ptr(); }
inline Dynamic &
Data::as_dyn()
    { return access_Dyn(); }
inline Array &
Data::as_array()
    { return access_Array(); }
inline Map &
Data::as_map()
    { return access_Map(); }
inline Struct &
Data::as_struct()
    { return access_Struct(); }

inline void
Data::acquire() const
    { ++nRefCount; }
inline Data::E_RefCount
Data::release() const
    { return --nRefCount == 0 ? free : used; }

inline void
Data::bin_write( csv::bostream & o_out ) const
    { do_BinWrite(o_out); }


}   // namespace udm


#endif


