/** Servant for TypeSuport interface of <%TYPE%> data type.
 *
 * See the DDS specification, OMG formal/04-12-02, for a description of
 * this interface.
 *
 */
class <%EXPORT%> <%TYPE%>TypeSupportImpl
  : public virtual OpenDDS::DCPS::LocalObject<<%TYPE%>TypeSupport>
  , public virtual OpenDDS::DCPS::TypeSupportImpl
{
public:

  //Constructor
  <%TYPE%>TypeSupportImpl ();

  //Destructor
  virtual ~<%TYPE%>TypeSupportImpl ();

  virtual
  DDS::ReturnCode_t register_type (::DDS::DomainParticipant_ptr participant,
                                   const char * type_name)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual char * get_type_name () ACE_THROW_SPEC ((CORBA::SystemException));

  virtual ::DDS::DataWriter_ptr create_datawriter ()
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual ::DDS::DataReader_ptr create_datareader ()
    ACE_THROW_SPEC ((CORBA::SystemException));

#ifndef OPENDDS_NO_CONTENT_SUBSCRIPTION_PROFILE
  virtual ::DDS::DataReader_ptr create_multitopic_datareader()
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual const OpenDDS::DCPS::MetaStruct& getMetaStructForType();
#endif


private:
  CORBA::String_var type_name_;
};

/** Servant for DataWriter interface of the <%TYPE%> data type.
 *
 * See the DDS specification, OMG formal/04-12-02, for a description of
 * this interface.
 */
class <%EXPORT%> <%TYPE%>DataWriterImpl
  : public virtual OpenDDS::DCPS::LocalObject<<%TYPE%>DataWriter>,
    public virtual OpenDDS::DCPS::DataWriterImpl
{
public:

  typedef std::map<<%SCOPED%>, DDS::InstanceHandle_t,
      OpenDDSGenerated::<%TYPE%>_KeyLessThan> InstanceMap;
  typedef ::OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow<ACE_Null_Mutex>  DataAllocator;

  //Constructor
  <%TYPE%>DataWriterImpl (void);

  //Destructor
  virtual ~<%TYPE%>DataWriterImpl (void);

  virtual DDS::InstanceHandle_t register_instance (
      const ::<%SCOPED%> & instance)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual DDS::InstanceHandle_t register_instance_w_timestamp (
      const ::<%SCOPED%> & instance,
      ::DDS::InstanceHandle_t handle,
      const ::DDS::Time_t & timestamp)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual DDS::ReturnCode_t unregister_instance (
      const ::<%SCOPED%> & instance,
      ::DDS::InstanceHandle_t handle)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual DDS::ReturnCode_t unregister_instance_w_timestamp (
      const ::<%SCOPED%> & instance,
      ::DDS::InstanceHandle_t handle,
      const ::DDS::Time_t & timestamp)
    ACE_THROW_SPEC ((CORBA::SystemException));

  //WARNING: If the handle is non-nil and the instance is not registered
  //         then this operation may cause an access violation.
  //         This lack of safety helps performance.
  virtual DDS::ReturnCode_t write (
      const ::<%SCOPED%> & instance_data,
      ::DDS::InstanceHandle_t handle)
    ACE_THROW_SPEC ((CORBA::SystemException));

  //WARNING: If the handle is non-nil and the instance is not registered
  //         then this operation may cause an access violation.
  //         This lack of safety helps performance.
  virtual DDS::ReturnCode_t write_w_timestamp (
      const ::<%SCOPED%> & instance_data,
      ::DDS::InstanceHandle_t handle,
      const ::DDS::Time_t & source_timestamp)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual DDS::ReturnCode_t dispose (
      const ::<%SCOPED%> & instance_data,
      ::DDS::InstanceHandle_t instance_handle)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual DDS::ReturnCode_t dispose_w_timestamp (
      const ::<%SCOPED%> & instance_data,
      ::DDS::InstanceHandle_t instance_handle,
      const ::DDS::Time_t & source_timestamp)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual DDS::ReturnCode_t get_key_value (
      ::<%SCOPED%> & key_holder,
      ::DDS::InstanceHandle_t handle)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual ::DDS::InstanceHandle_t lookup_instance (
      const ::<%SCOPED%> & instance_data)
    ACE_THROW_SPEC ((CORBA::SystemException));

  /**
   * Initialize the DataWriter object.
   * Called as part of create_datawriter.
   */
  virtual void init (
        ::DDS::Topic_ptr                       topic,
        OpenDDS::DCPS::TopicImpl*              topic_servant,
        const ::DDS::DataWriterQos &           qos,
        ::DDS::DataWriterListener_ptr          a_listener,
        const ::DDS::StatusMask &              mask,
        OpenDDS::DCPS::DomainParticipantImpl*  participant_servant,
        OpenDDS::DCPS::PublisherImpl*          publisher_servant,
        ::DDS::DataWriter_ptr                  dw_objref,
        ::OpenDDS::DCPS::DataWriterRemote_ptr  dw_remote_objref
      )
    ACE_THROW_SPEC ((CORBA::SystemException));

  /**
   * Do parts of enable specific to the datatype.
   * Called by DataWriterImpl::enable().
   */
  virtual ::DDS::ReturnCode_t enable_specific ()
    ACE_THROW_SPEC ((CORBA::SystemException));

  /**
   * The framework has completed its part of unregistering the
   * given instance.
   */
  virtual void unregistered(::DDS::InstanceHandle_t instance_handle);

  /**
   * Accessor to the marshalled data sample allocator.
   */
  ACE_INLINE
  DataAllocator* data_allocator () const  {
    return data_allocator_;
  };

private:

  /**
   * Serialize the instance data.
   *
   * @param instance_data The data to serialize.
   * @param for_write If 1 use the fast allocator; otherwise use the heap.
   * @return returns the serialized data.
   */
  ACE_Message_Block* dds_marshal(
    const ::<%SCOPED%>& instance_data,
    int  for_write = 1);

  /**
   * Find the instance handle for the given instance_data using
   * the data type's key(s).  If the instance does not already exist
   * create a new instance handle for it.
   */
  ::DDS::ReturnCode_t get_or_create_instance_handle(
    DDS::InstanceHandle_t& handle,
    const ::<%SCOPED%>& instance_data,
    const ::DDS::Time_t & source_timestamp);

   InstanceMap  instance_map_;
   size_t       marshaled_size_;
   // The lock pool will be thread safe because
   // only one write call is allowed at a time.
   DataBlockLockPool*  db_lock_pool_;
   DataAllocator* data_allocator_;
   ::OpenDDS::DCPS::MessageBlockAllocator* mb_allocator_;
   ::OpenDDS::DCPS::DataBlockAllocator*    db_allocator_;
};

/** Servant for DataReader interface of <%TYPE%> data type.
 *
 * See the DDS specification, OMG formal/04-12-02, for a description of
 * this interface.
 *
 */
class <%EXPORT%> <%TYPE%>DataReaderImpl
  : public virtual OpenDDS::DCPS::LocalObject<<%TYPE%>DataReader>,
    public virtual OpenDDS::DCPS::DataReaderImpl
{
public:

  typedef std::map<<%SCOPED%>, DDS::InstanceHandle_t,
      OpenDDSGenerated::<%TYPE%>_KeyLessThan> InstanceMap;
  typedef ::OpenDDS::DCPS::Cached_Allocator_With_Overflow<<%SCOPED%>, ACE_Null_Mutex>  DataAllocator;
  typedef <%TYPE%>DataReader Interface;

  //Constructor
  <%TYPE%>DataReaderImpl (void);

  //Destructor
  virtual ~<%TYPE%>DataReaderImpl (void);

  virtual DDS::ReturnCode_t delete_contained_entities ()
    ACE_THROW_SPEC ((CORBA::SystemException));

  /**
   * Do parts of enable specific to the datatype.
   * Called by DataReaderImpl::enable().
   */
  virtual ::DDS::ReturnCode_t enable_specific ()
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual DDS::ReturnCode_t read (
      ::<%SCOPED%>Seq & received_data,
      ::DDS::SampleInfoSeq & info_seq,
      ::CORBA::Long max_samples,
      ::DDS::SampleStateMask sample_states,
      ::DDS::ViewStateMask view_states,
      ::DDS::InstanceStateMask instance_states)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual DDS::ReturnCode_t take (
      ::<%SCOPED%>Seq & received_data,
      ::DDS::SampleInfoSeq & info_seq,
      ::CORBA::Long max_samples,
      ::DDS::SampleStateMask sample_states,
      ::DDS::ViewStateMask view_states,
      ::DDS::InstanceStateMask instance_states)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual ::DDS::ReturnCode_t read_w_condition (
      ::<%SCOPED%>Seq & data_values,
      ::DDS::SampleInfoSeq & sample_infos,
      ::CORBA::Long max_samples,
      ::DDS::ReadCondition_ptr a_condition)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual ::DDS::ReturnCode_t take_w_condition (
      ::<%SCOPED%>Seq & data_values,
      ::DDS::SampleInfoSeq & sample_infos,
      ::CORBA::Long max_samples,
      ::DDS::ReadCondition_ptr a_condition)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual DDS::ReturnCode_t read_next_sample (
      ::<%SCOPED%> & received_data,
      ::DDS::SampleInfo & sample_info)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual DDS::ReturnCode_t take_next_sample (
      ::<%SCOPED%> & received_data,
      ::DDS::SampleInfo & sample_info)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual DDS::ReturnCode_t read_instance (
      ::<%SCOPED%>Seq & received_data,
      ::DDS::SampleInfoSeq & info_seq,
      ::CORBA::Long max_samples,
      ::DDS::InstanceHandle_t a_handle,
      ::DDS::SampleStateMask sample_states,
      ::DDS::ViewStateMask view_states,
      ::DDS::InstanceStateMask instance_states)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual DDS::ReturnCode_t take_instance (
      ::<%SCOPED%>Seq & received_data,
      ::DDS::SampleInfoSeq & info_seq,
      ::CORBA::Long max_samples,
      ::DDS::InstanceHandle_t a_handle,
      ::DDS::SampleStateMask sample_states,
      ::DDS::ViewStateMask view_states,
      ::DDS::InstanceStateMask instance_states)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual DDS::ReturnCode_t read_next_instance (
      ::<%SCOPED%>Seq & received_data,
      ::DDS::SampleInfoSeq & info_seq,
      ::CORBA::Long max_samples,
      ::DDS::InstanceHandle_t a_handle,
      ::DDS::SampleStateMask sample_states,
      ::DDS::ViewStateMask view_states,
      ::DDS::InstanceStateMask instance_states)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual DDS::ReturnCode_t take_next_instance (
      ::<%SCOPED%>Seq & received_data,
      ::DDS::SampleInfoSeq & info_seq,
      ::CORBA::Long max_samples,
      ::DDS::InstanceHandle_t a_handle,
      ::DDS::SampleStateMask sample_states,
      ::DDS::ViewStateMask view_states,
      ::DDS::InstanceStateMask instance_states)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual ::DDS::ReturnCode_t read_next_instance_w_condition (
      ::<%SCOPED%>Seq & data_values,
      ::DDS::SampleInfoSeq & sample_infos,
      ::CORBA::Long max_samples,
      ::DDS::InstanceHandle_t previous_handle,
      ::DDS::ReadCondition_ptr a_condition)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual ::DDS::ReturnCode_t take_next_instance_w_condition (
      ::<%SCOPED%>Seq & data_values,
      ::DDS::SampleInfoSeq & sample_infos,
      ::CORBA::Long max_samples,
      ::DDS::InstanceHandle_t previous_handle,
      ::DDS::ReadCondition_ptr a_condition)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual DDS::ReturnCode_t return_loan (
      ::<%SCOPED%>Seq & received_data,
      ::DDS::SampleInfoSeq & info_seq)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual DDS::ReturnCode_t get_key_value (
      ::<%SCOPED%> & key_holder,
      ::DDS::InstanceHandle_t handle)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual ::DDS::InstanceHandle_t lookup_instance (
      const ::<%SCOPED%> & instance_data)
    ACE_THROW_SPEC ((CORBA::SystemException));

  virtual DDS::ReturnCode_t auto_return_loan(void* seq);

  void release_loan (::<%SCOPED%>Seq & received_data);

  void dec_ref_data_element(::OpenDDS::DCPS::ReceivedDataElement* r);

  virtual void delete_instance_map (void* map);

#ifndef OPENDDS_NO_CONTENT_SUBSCRIPTION_PROFILE
  bool contains_sample_filtered(DDS::SampleStateMask sample_states,
                                DDS::ViewStateMask view_states,
                                DDS::InstanceStateMask instance_states,
                                const OpenDDS::DCPS::FilterEvaluator& evaluator,
                                const DDS::StringSeq& params);

  DDS::ReturnCode_t read_generic(
    OpenDDS::DCPS::DataReaderImpl::GenericBundle& gen,
    DDS::SampleStateMask sample_states, DDS::ViewStateMask view_states,
    DDS::InstanceStateMask instance_states);

  DDS::InstanceHandle_t lookup_instance_generic(const void* data);

  DDS::ReturnCode_t read_instance_generic(void*& data,
    DDS::SampleInfo& info, DDS::InstanceHandle_t instance,
    DDS::SampleStateMask sample_states, DDS::ViewStateMask view_states,
    DDS::InstanceStateMask instance_states);

  DDS::ReturnCode_t read_next_instance_generic(void*& data,
    DDS::SampleInfo& info, DDS::InstanceHandle_t previous_instance,
    DDS::SampleStateMask sample_states, DDS::ViewStateMask view_states,
    DDS::InstanceStateMask instance_states);

  DDS::InstanceHandle_t store_synthetic_data(const <%SCOPED%>& sample,
                                             DDS::ViewStateKind view);

  void set_instance_state(DDS::InstanceHandle_t instance,
                          DDS::InstanceStateKind state);
#endif

  virtual void lookup_instance(const OpenDDS::DCPS::ReceivedDataSample& sample,
                               OpenDDS::DCPS::SubscriptionInstance*& instance);

 protected:

    virtual void dds_demarshal(const OpenDDS::DCPS::ReceivedDataSample& sample,
                               OpenDDS::DCPS::SubscriptionInstance*& instance,
                               bool & just_registered,
                               bool & filtered);

    virtual void dispose(const OpenDDS::DCPS::ReceivedDataSample& sample,
                         OpenDDS::DCPS::SubscriptionInstance*& instance);

    virtual void unregister(const OpenDDS::DCPS::ReceivedDataSample& sample,
                            OpenDDS::DCPS::SubscriptionInstance*& instance);

    //virtual OpenDDS::DCPS::DataReaderRemote_ptr get_datareaderremote_obj_ref ();

    virtual void purge_data(OpenDDS::DCPS::SubscriptionInstance* instance);

    virtual void release_instance_i (::DDS::InstanceHandle_t handle);

  private:

    ::DDS::ReturnCode_t read_i (
      ::<%SCOPED%>Seq & received_data,
      ::DDS::SampleInfoSeq & info_seq,
      ::CORBA::Long max_samples,
      ::DDS::SampleStateMask sample_states,
      ::DDS::ViewStateMask view_states,
      ::DDS::InstanceStateMask instance_states,
      ::DDS::QueryCondition_ptr a_condition
      );

    ::DDS::ReturnCode_t take_i (
      ::<%SCOPED%>Seq & received_data,
      ::DDS::SampleInfoSeq & info_seq,
      ::CORBA::Long max_samples,
      ::DDS::SampleStateMask sample_states,
      ::DDS::ViewStateMask view_states,
      ::DDS::InstanceStateMask instance_states,
      ::DDS::QueryCondition_ptr a_condition
      );

    DDS::ReturnCode_t read_instance_i (
      ::<%SCOPED%>Seq & received_data,
      ::DDS::SampleInfoSeq & info_seq,
      ::CORBA::Long max_samples,
      ::DDS::InstanceHandle_t a_handle,
      ::DDS::SampleStateMask sample_states,
      ::DDS::ViewStateMask view_states,
      ::DDS::InstanceStateMask instance_states,
      ::DDS::QueryCondition_ptr a_condition
      );

    DDS::ReturnCode_t take_instance_i (
      ::<%SCOPED%>Seq & received_data,
      ::DDS::SampleInfoSeq & info_seq,
      ::CORBA::Long max_samples,
      ::DDS::InstanceHandle_t a_handle,
      ::DDS::SampleStateMask sample_states,
      ::DDS::ViewStateMask view_states,
      ::DDS::InstanceStateMask instance_states,
      ::DDS::QueryCondition_ptr a_condition
      );

    DDS::ReturnCode_t read_next_instance_i (
      ::<%SCOPED%>Seq & received_data,
      ::DDS::SampleInfoSeq & info_seq,
      ::CORBA::Long max_samples,
      ::DDS::InstanceHandle_t a_handle,
      ::DDS::SampleStateMask sample_states,
      ::DDS::ViewStateMask view_states,
      ::DDS::InstanceStateMask instance_states,
      ::DDS::QueryCondition_ptr a_condition
      );

    DDS::ReturnCode_t take_next_instance_i (
      ::<%SCOPED%>Seq & received_data,
      ::DDS::SampleInfoSeq & info_seq,
      ::CORBA::Long max_samples,
      ::DDS::InstanceHandle_t a_handle,
      ::DDS::SampleStateMask sample_states,
      ::DDS::ViewStateMask view_states,
      ::DDS::InstanceStateMask instance_states,
      ::DDS::QueryCondition_ptr a_condition
      );

    void store_instance_data(
         ::<%SCOPED%> *instance_data,
         const OpenDDS::DCPS::DataSampleHeader& header,
         OpenDDS::DCPS::SubscriptionInstance*& instance_ptr,
         bool & just_registered,
         bool & filtered
         );

    /// common input read* & take* input processing and precondition checks
    ::DDS::ReturnCode_t check_inputs (
        const char* method_name,
        ::<%SCOPED%>Seq & received_data,
        ::DDS::SampleInfoSeq & info_seq,
        ::CORBA::Long max_samples
        );

   InstanceMap  instance_map_;
   DataAllocator* data_allocator_;
};
