// **********************************************************************
//
// Copyright (c) 2002
// IONA Technologies, Inc.
// Waltham, MA, USA
//
// All Rights Reserved
//
// **********************************************************************

#ifndef OB_VALUE_BASE_H
#define OB_VALUE_BASE_H

#include <OB/ValueBase_fwd.h>
#include <OB/ValueFactoryBase_fwd.h>
#include <OB/AbstractBase_fwd.h>
#include <OB/ORBInstance_fwd.h>

#include <OB/POAServantBase.h>

namespace OB
{

class ValueBaseInfo : public ConstructedInfo
{
public:

    ValueBaseInfo() { }
    virtual ~ValueBaseInfo() { }

    //
    // void* memory handling
    //
    virtual void free(void*) const;
    virtual void* dup(const void*) const;

    //
    // CDR
    //
    virtual void marshal(const void*, OutputStreamImpl*) const;
    virtual void unmarshal(void*, InputStreamImpl*) const;
};

} // End of namespace OB

namespace CORBA
{

class ValueBase
{
    //
    // Not implemented
    //
    void operator=(const ValueBase&);

    static const char* _ob_id_;
    static const char* _ob_truncatable_ids_[];

protected:

    ValueBase();
    ValueBase(const ValueBase&);
    
    virtual ~ValueBase();

public:

    static OB::ValueBaseInfo _OB_valueBaseInfo;

    virtual ValueBase* _add_ref() = 0;
    virtual void _remove_ref() = 0;
    virtual ULong _refcount_value() = 0;
    virtual ValueBase* _copy_value() = 0;

    virtual ValueDef_ptr _get_value_def();

    static ValueBase* _downcast(ValueBase*);
    static ValueBase* _downcast(AbstractBase_ptr);

    virtual const char* _OB_typeId() const;
    static const char* _OB_id();
    virtual const char** _OB_truncatableIds() const;

    virtual Boolean _OB_isCustom() const;
    virtual Boolean _OB_isTruncatable() const;

    virtual AbstractBase_ptr _OB_toAbstractBase();

    virtual void _OB_marshal(OB::OutputStreamImpl*);
    virtual void _OB_unmarshal(OB::InputStreamImpl*);

    static ValueBase* _OB_createValue(OB::ORBInstance_ptr,
                                      const OB::StrSeq< int >&,
                                      const char*);
    static ValueBase* _OB_createValue(CORBA::ValueFactoryBase*);
};

inline void
add_ref(ValueBase* vb)
{
    if(vb != 0)
        vb -> _add_ref();
}

inline void
remove_ref(ValueBase* vb)
{
    if(vb != 0)
        vb -> _remove_ref();
}

class DefaultValueRefCountBase : public virtual ValueBase,
                                 public virtual OB::RefCount
{
private:

    //
    // Not implemented
    //
    void operator=(const DefaultValueRefCountBase&);

protected:

    DefaultValueRefCountBase();
    DefaultValueRefCountBase(const DefaultValueRefCountBase&);
    virtual ~DefaultValueRefCountBase();

public:

    virtual ValueBase* _add_ref();
    virtual void _remove_ref();
    virtual ULong _refcount_value();
};

} // End of namespace CORBA

namespace OB
{

//
// This class is necessary because ValueBase::_add_ref() returns
// ValueBase*, whereas ServantBase::_add_ref() returns void. So we
// need an intermediate class to implement ValueBase::_add_ref().
//
class ValueRefCountBaseHelper : public virtual CORBA::ValueBase
{
private:

    //
    // Not implemented
    //
    void operator=(const ValueRefCountBaseHelper&);

    virtual void servantAddRefImpl() = 0;

public:

    virtual CORBA::ValueBase* _add_ref()
    {
        servantAddRefImpl();
        return this;
    }
};

} // End of namespace OB

namespace PortableServer
{

//
// class PortableServer::ValueRefCountBase
//

class ValueRefCountBase : public virtual OB::ValueRefCountBaseHelper,
                          public virtual RefCountServantBase
{
private:

    //
    // Not implemented
    //
    void operator=(const ValueRefCountBase&);

    virtual void servantAddRefImpl();

protected:

    ValueRefCountBase();
    ValueRefCountBase(const ValueRefCountBase&);
    virtual ~ValueRefCountBase();

public:

    virtual void _remove_ref();
    virtual CORBA::ULong _refcount_value();
};

} // End of namespace PortableServer

#endif
