/***********************************************************************
  IEEE 1516.1 High Level Architecture Interface Specification C++ API
  File: RTI/Handle.h
***********************************************************************/

#ifndef RTI_Handle_h
#define RTI_Handle_h

#include <RTI/SpecificConfig.h>
#include <RTI/Exception.h>
#include <RTI/VariableLengthData.h>
#include <string>

// The following macro is used to define each of the Handle classes
// that are used by the RTI's API, e.g. AttributeHandle, ParameterHandle, etc.
// Each kind of handle contains the same set of operators and functions, but
// each is a separate class for type safety.  The encode method can be used to
// generate an encoded value for a handle, that can be sent to other federates 
// as an attribute or parameter.  (Use RTIambassador functions to reconstruct a 
// handle from an encoded value).  RTI implementations contain definitions
// for each kind of the HandleKindImplementation classes (e.g. 
// AttributeHandleImplementation), but these classes are not needed by 
// federate code.

#define DEFINE_HANDLE_CLASS(HandleKind)                         \
                                                                \
/* Forward declaration for the RTI-internal class            */ \
/* used to implement a specific kind of handle               */ \
class RTI_EXPORT HandleKind##Implementation;                    \
                                                                \
/* Each handle class generated by this macro provides the    */ \
/* following interface                                       */ \
class RTI_EXPORT HandleKind                                     \
{                                                               \
public:                                                         \
                                                                \
   /* Constructs an invalid handle                           */ \
   HandleKind();                                                \
                                                                \
   ~HandleKind()                                                \
      throw();                                                  \
                                                                \
   HandleKind(HandleKind const & rhs);                          \
                                                                \
   HandleKind &                                                 \
      operator=(HandleKind const & rhs);                        \
                                                                \
   /* Indicates whether this handle is valid                 */ \
   bool isValid() const;                                        \
                                                                \
   /* All invalid handles are equivalent                     */ \
   bool operator==(HandleKind const & rhs) const;               \
   bool operator!=(HandleKind const & rhs) const;               \
   bool operator< (HandleKind const & rhs) const;               \
                                                                \
   /* Generate an encoded value that can be used to send     */ \
   /* handles to other federates in updates or interactions. */ \
   VariableLengthData encode() const;                           \
                                                                \
   /* Alternate encode for directly filling a buffer         */ \
   unsigned long encodedLength() const;                         \
   unsigned long encode(                                        \
      void* buffer, unsigned long bufferSize) const             \
      throw (CouldNotEncode);                                   \
                                                                \
   std::wstring toString() const;                               \
                                                                \
protected:                                                      \
                                                                \
   /* Friend declaration for an RTI-internal class that      */ \
   /* can access the implementation of a handle.             */ \
   friend class HandleKind##Friend;                             \
                                                                \
   const HandleKind##Implementation* getImplementation() const; \
                                                                \
   HandleKind##Implementation* getImplementation();             \
                                                                \
   explicit                                                     \
      HandleKind(HandleKind##Implementation* impl);             \
                                                                \
   explicit                                                     \
      HandleKind(VariableLengthData const & encodedValue);      \
                                                                \
   HandleKind##Implementation* _impl;                           \
                                                                \
};                                                              \
                                                                \
/* Output operator for Handles                               */ \
std::wostream RTI_EXPORT &                                       \
  operator << (std::wostream &, HandleKind const &);


namespace rti1516
{

// All of the RTI API's Handle classes are defined 
// by invoking the macro above.
DEFINE_HANDLE_CLASS(FederateHandle)
DEFINE_HANDLE_CLASS(ObjectClassHandle)
DEFINE_HANDLE_CLASS(InteractionClassHandle)
DEFINE_HANDLE_CLASS(ObjectInstanceHandle)
DEFINE_HANDLE_CLASS(AttributeHandle)
DEFINE_HANDLE_CLASS(ParameterHandle)
DEFINE_HANDLE_CLASS(DimensionHandle)
DEFINE_HANDLE_CLASS(MessageRetractionHandle)
DEFINE_HANDLE_CLASS(RegionHandle)
  
}

#endif // RTI_Handle_h

