/*
 *                         OpenSplice DDS
 *
 *   This software and documentation are Copyright 2006 to TO_YEAR PrismTech
 *   Limited, its affiliated companies and licensors. All rights reserved.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */
#ifndef OMG_DDS_CORE_DETAIL_PROPRIETARY_API_HPP_
#define OMG_DDS_CORE_DETAIL_PROPRIETARY_API_HPP_

/*
 * There are two parts in the IsoCpp API:
 *   - Specification API (include/dds)
 *   - Proprietary API   (include/org)
 * However, include/org mostly contains implementation details and only a small
 * part is API for the application.
 *
 * There are basically two ways of including the proprietary API into the API
 * documentation generated by doxygen.
 *
 * 1) Add include/org to the doxygen input directories and filter out the
 *    non-API information (see doxygen_isocpp2_*.cfg files)
 *      Advantage -
 *          Documentation is at the same place as the implementation.
 *      Disadvantage -
 *          The non-API filtering can be done by either changing the doxygen
 *          config files or adding cond/endcond tags all through the header
 *          files. Both will be quite cumbersome.
 * 2) Add a header file to include/dds that contains the documentation for the
 *    proprietary part of the API.
 *      Advantage -
 *          Simple.
 *      Disadvantage -
 *          Documentation is in a different place as the implementation.
 *
 * Option 2 is choosen (obviously, because you're looking at that actual
 * proprietary API documentation file).
 */

#ifdef DOXYGEN_FOR_ISOCPP2
/*
 * The above macro is never (and must never) be defined in normal compilation.
 *
 * The following code is only for documentation purposes.
 */


namespace org {
namespace opensplice {



namespace topic {

    /**
     * @brief
     * Topic proprietary events Listener
     *
     * Since a Topic is an Entity, it has the ability to have a Listener
     * associated with it. In this case, the associated Listener should be of type
     * TopicListener. This interface must be implemented by the
     * application. A user-defined class must be provided by the application which must
     * extend from the TopicListener class.
     *
     * This proprietary listener is a child of the specification listener and is made
     * available to be able to trigger the on_all_data_disposed() proprietary event.
     *
     * <b><i>
     * All operations for this interface must be implemented in the user-defined class, it is
     * up to the application whether an operation is empty or contains some functionality.
     * </i></b>
     *
     * The TopicListener provides a generic mechanism (actually a
     * callback function) for the Data Distribution Service to notify the application of
     * relevant asynchronous status change events, such as a missed deadline, violation of
     * a QosPolicy setting, etc. The TopicListener is related to
     * changes in communication status StatusConditions.
     *
     * @code{.cpp}
     * // Application example listener
     * class ExampleListener :
     *                public virtual org::opensplice::topic::TopicListener<Foo::Bar>
     * {
     * public:
     *     virtual void on_all_data_disposed (
     *         dds::topic::Topic<Foo::Bar>& topic,
     *         const org::opensplice::core::status::AllDataDisposedTopicStatus& status)
     *     {
     *         std::cout << "on_all_data_disposed" << std::endl;
     *     }
     *
     *     virtual void on_inconsistent_topic (
     *         dds::topic::Topic<Foo::Bar>& topic,
     *         const dds::core::status::InconsistentTopicStatus& status)
     *     {
     *         std::cout << "on_inconsistent_topic" << std::endl;
     *     }
     * };
     *
     * // Create Topic with the listener
     * dds::domain::DomainParticipant participant(org::opensplice::domain::default_id());
     * dds::topic::Topic<Foo::Bar> topic(participant,
     *                                   "TopicName",
     *                                   participant.default_topic_qos(),
     *                                   new ExampleListener(),
     *                                   dds::core::status::StatusMask::all());
     *
     * @endcode
     *
     * @see @ref DCPS_Modules_Topic "Topic"
     * @see @ref DCPS_Modules_Infrastructure_Listener "Listener information"
     */
    template <typename T>
    class TopicListener : public dds::topic::TopicListener<T>
    {
    public:
        /**
         * This operation is called by the Data Distribution Service when the
         * AllDataDisposedTopicStatus changes.
         *
         * The implementation may be left empty
         * when this functionality is not needed. This operation will only be called when the
         * relevant TopicListener is installed and enabled with the
         * dds::core::status::StatusMask::all_data_disposed_topic(). The AllDataDisposedTopicStatus
         * will change when the node has completed disposal of data as a result of a call to
         * dds::topic::AnyTopic::dispose_all_data().
         *
         * @param topic  contain a pointer to the Topic on which the conflict
         *               occurred (this is an input to the application).
         * @param status contain the AllDataDisposedTopicStatus object (this is
         *               an input to the application).
         */
        virtual void on_all_data_disposed(
            dds::topic::Topic<T>& topic,
            const org::opensplice::core::status::AllDataDisposedTopicStatus& status) = 0;
    };

    /**
     * @brief
     * Topic proprietary events Listener
     *
     * This listener is just like TopicListener, except
     * that the application doesn't have to implement all operations.
     *
     * This proprietary listener is a child of the specification listener and is made
     * available to be able to trigger the on_all_data_disposed() proprietary event.
     *
     * @code{.cpp}
     * class ExampleListener : public virtual org::opensplice::topic::NoOpTopicListener<Foo::Bar>
     * {
     *    // Not necessary to implement any Listener operations.
     * };
     * @endcode
     *
     * @see dds::topic::TopicListener
     */
    template <typename T>
    class NoOpTopicListener : public virtual TopicListener<T>
    { };

    /**
     * @brief
     * AnyTopic proprietary events Listener
     *
     * Because the DomainParticipant does not have knowledge of data types,
     * it has to use non-data-type-listeners. In other words Any* listeners.
     *
     * This proprietary listener is a child of the specification listener and is made
     * available to be able to trigger the on_all_data_disposed() proprietary event.
     *
     * <b><i>
     * All operations for this interface must be implemented in the user-defined class, it is
     * up to the application whether an operation is empty or contains some functionality.
     * </i></b>
     *
     * This class is used as a base for other listeners and is not used on its own.
     *
     * @see org::opensplice::domain::DomainParticipantListener
     */
    class AnyTopicListener : public virtual dds::topic::AnyTopicListener
    {
    public:
        /** @copydoc org::opensplice::topic::TopicListener::on_all_data_disposed() */
        virtual void on_all_data_disposed(
            dds::topic::AnyTopic& topic,
            const org::opensplice::core::status::AllDataDisposedTopicStatus& status) = 0;
    };

    /**
     * @brief
     * AnyTopic proprietary events Listener
     *
     * This listener is just like AnyTopicListener, except
     * that the application doesn't have to implement all operations.
     *
     * This proprietary listener is a child of the specification listener and is made
     * available to be able to trigger the on_all_data_disposed() proprietary event.
     *
     * This class is used as a base for other listeners and is not used on its own.
     *
     * @see org::opensplice::topic::AnyTopicListener
     * @see org::opensplice::domain::NoOpDomainParticipantListener
     */
    class NoOpAnyTopicListener : public virtual AnyTopicListener
    { };


    /**
     * @brief
     * The proprietary builtin CMParticipantBuiltinTopicData topic.
     *
     * This topic is normally only used by OpenSplice tools.
     *
     * @note
     * Users are discouraged from doing anything with this topic, so as not to interfere
     * with internal mechanisms that rely on them. The structure of these topics may
     * change without notification.
     */
    class CMParticipantBuiltinTopicData : public dds::core::Value
    {
    public:
        const dds::topic::BuiltinTopicKey& key() const
        const org::opensplice::core::policy::ProductData&   product() const
    };

    /**
     * @brief
     * The proprietary builtin CMPublisherBuiltinTopicData topic.
     *
     * This topic is normally only used by OpenSplice tools.
     *
     * @note
     * Users are discouraged from doing anything with this topic, so as not to interfere
     * with internal mechanisms that rely on them. The structure of these topics may
     * change without notification.
     */
    class CMPublisherBuiltinTopicData : public dds::core::Value
    {
    public:
        const dds::topic::BuiltinTopicKey& key() const
        const org::opensplice::core::policy::ProductData& product() const
        const dds::topic::BuiltinTopicKey& participant_key() const
        const std::string& name() const
        const dds::core::policy::EntityFactory& entity_factory() const
        const dds::core::policy::Partition& partition() const
    };

    /**
     * @brief
     * The proprietary builtin CMSubscriberBuiltinTopicData topic.
     *
     * This topic is normally only used by OpenSplice tools.
     *
     * @note
     * Users are discouraged from doing anything with this topic, so as not to interfere
     * with internal mechanisms that rely on them. The structure of these topics may
     * change without notification.
     */
    class CMSubscriberBuiltinTopicData : public dds::core::Value
    {
    public:
        const dds::topic::BuiltinTopicKey& key() const
        const org::opensplice::core::policy::ProductData&   product() const
        const dds::topic::BuiltinTopicKey& participant_key() const
        const std::string& name() const
        const dds::core::policy::EntityFactory& entity_factory() const
        const dds::core::policy::Partition& partition() const
        const org::opensplice::core::policy::Share& share() const
    };

    /**
     * @brief
     * The proprietary builtin CMDataWriter topic.
     *
     * This topic is normally only used by OpenSplice tools.
     *
     * @note
     * Users are discouraged from doing anything with this topic, so as not to interfere
     * with internal mechanisms that rely on them. The structure of these topics may
     * change without notification.
     */
    class CMDataWriterBuiltinTopicData : public dds::core::Value
    {
    public:
        const dds::topic::BuiltinTopicKey& key() const
        const org::opensplice::core::policy::ProductData& product() const
        const dds::topic::BuiltinTopicKey& publisher_key() const
        const std::string& name() const
        const dds::core::policy::History& history() const
        const dds::core::policy::ResourceLimits& resource_limits() const
        const dds::core::policy::WriterDataLifecycle& writer_data_lifecycle() const
    };

    /**
     * @brief
     * The proprietary builtin CMDataReader topic.
     *
     * This topic is normally only used by OpenSplice tools.
     *
     * @note
     * Users are discouraged from doing anything with this topic, so as not to interfere
     * with internal mechanisms that rely on them. The structure of these topics may
     * change without notification.
     */
    class CMDataReaderBuiltinTopicData : public dds::core::Value
    {
    public:
        const dds::topic::BuiltinTopicKey& key() const
        const org::opensplice::core::policy::ProductData& product() const
        const dds::topic::BuiltinTopicKey& subscriber_key() const
        const std::string& name() const
        const dds::core::policy::History& history() const
        const dds::core::policy::ResourceLimits& resource_limits() const
        const dds::core::policy::ReaderDataLifecycle& reader_data_lifecycle() const
        const org::opensplice::core::policy::SubscriptionKey& subscription_keys() const
        const org::opensplice::core::policy::ReaderLifespan& reader_lifespan() const
        const org::opensplice::core::policy::Share& share() const
    };


} /* namespace topic */




namespace domain {

    /**
     * This domain ID causes the creation of a DomainParticipant to
     * use the domain ID that is provided within the configuration
     * or 0 when no ID was provided (which is the default).
     *
     * @return default domain id
     */
    uint32_t default_id();

    /**
     * @brief
     * DomainParticipant proprietary events Listener
     *
     * Since a DomainParticipant is an Entity, it has the ability to have a Listener
     * associated with it. In this case, the associated Listener should be of type
     * DomainParticipantListener. This interface must be implemented by the
     * application. A user-defined class must be provided by the application which must
     * extend from the DomainParticipantListener class.
     *
     * This proprietary listener is a child of the specification listener and is made
     * available to be able to trigger the on_all_data_disposed() proprietary event.
     *
     * <b><i>
     * All operations for this interface must be implemented in the user-defined class, it is
     * up to the application whether an operation is empty or contains some functionality.
     * </i></b>
     *
     * The DomainParticipantListener provides a generic mechanism (actually a
     * callback function) for the Data Distribution Service to notify the application of
     * relevant asynchronous status change events, such as a missed deadline, violation of
     * a QosPolicy setting, etc. The DomainParticipantListener is related to
     * changes in communication status StatusConditions.
     *
     * @code{.cpp}
     * // Application example listener
     * class ExampleListener :
     *                public virtual org::opensplice::domain::DomainParticipantListener
     * {
     * public:
     *     virtual void on_all_data_disposed (
     *         dds::topic::AnyTopic& topic,
     *         const org::opensplice::core::status::AllDataDisposedTopicStatus& status)
     *     {
     *         std::cout << "on_all_data_disposed" << std::endl;
     *     }
     *
     *     virtual void on_inconsistent_topic (
     *         dds::topic::AnyTopic& topic,
     *         const dds::core::status::InconsistentTopicStatus& status)
     *     {
     *         std::cout << "on_inconsistent_topic" << std::endl;
     *     }
     *
     *     virtual void on_offered_deadline_missed (
     *         dds::pub::AnyDataWriter& writer,
     *         const dds::core::status::OfferedDeadlineMissedStatus& status)
     *     {
     *         std::cout << "on_offered_deadline_missed" << std::endl;
     *     }
     *
     *     virtual void on_offered_incompatible_qos (
     *         dds::pub::AnyDataWriter& writer,
     *         const dds::core::status::OfferedIncompatibleQosStatus& status)
     *     {
     *         std::cout << "on_offered_incompatible_qos" << std::endl;
     *     }
     *
     *     virtual void on_liveliness_lost (
     *         dds::pub::AnyDataWriter& writer,
     *         const dds::core::status::LivelinessLostStatus& status)
     *     {
     *         std::cout << "on_liveliness_lost" << std::endl;
     *     }
     *
     *     virtual void on_publication_matched (
     *         dds::pub::AnyDataWriter& writer,
     *         const dds::core::status::PublicationMatchedStatus& status)
     *     {
     *         std::cout << "on_publication_matched" << std::endl;
     *     }
     *
     *     virtual void on_requested_deadline_missed (
     *         dds::sub::AnyDataReader& reader,
     *         const dds::core::status::RequestedDeadlineMissedStatus & status)
     *     {
     *         std::cout << "on_requested_deadline_missed" << std::endl;
     *     }
     *
     *     virtual void on_requested_incompatible_qos (
     *         dds::sub::AnyDataReader& reader,
     *         const dds::core::status::RequestedIncompatibleQosStatus & status)
     *     {
     *         std::cout << "on_requested_incompatible_qos" << std::endl;
     *     }
     *
     *     virtual void on_sample_rejected (
     *         dds::sub::AnyDataReader& reader,
     *         const dds::core::status::SampleRejectedStatus & status)
     *     {
     *         std::cout << "on_sample_rejected" << std::endl;
     *     }
     *
     *     virtual void on_liveliness_changed (
     *         dds::sub::AnyDataReader& reader,
     *         const dds::core::status::LivelinessChangedStatus & status)
     *     {
     *         std::cout << "on_liveliness_changed" << std::endl;
     *     }
     *
     *     virtual void on_data_available (
     *         dds::sub::AnyDataReader& reader)
     *     {
     *         std::cout << "on_data_available" << std::endl;
     *     }
     *
     *     virtual void on_subscription_matched (
     *         dds::sub::AnyDataReader& reader,
     *         const dds::core::status::SubscriptionMatchedStatus & status)
     *     {
     *         std::cout << "on_subscription_matched" << std::endl;
     *     }
     *
     *     virtual void on_sample_lost (
     *         dds::sub::AnyDataReader& reader,
     *         const dds::core::status::SampleLostStatus & status)
     *     {
     *         std::cout << "on_sample_lost" << std::endl;
     *     }
     *
     *     virtual void on_data_on_readers (
     *         dds::sub::Subscriber& subs)
     *     {
     *         std::cout << "on_data_on_readers" << std::endl;
     *     }
     * };
     *
     * // Create DomainParticipant with the listener
     * dds::domain::DomainParticipant participant(org::opensplice::domain::default_id(),
     *                                            dds::domain::DomainParticipant::default_participant_qos(),
     *                                            new ExampleListener(),
     *                                            dds::core::status::StatusMask::all());
     *
     * @endcode
     *
     * @see @ref DCPS_Modules_DomainParticipant "Domain Participant"
     * @see @ref DCPS_Modules_Infrastructure_Listener "Listener information"
     */
    class DomainParticipantListener :
        public virtual dds::domain::DomainParticipantListener,
        public virtual org::opensplice::topic::AnyTopicListener
    { };

    /**
     * @brief
     * DomainParticipant proprietary events Listener
     *
     * This listener is just like DomainParticipantListener, except
     * that the application doesn't have to implement all operations.
     *
     * This proprietary listener is a child of the specification listener and is made
     * available to be able to trigger the on_all_data_disposed() proprietary event.
     *
     * @code{.cpp}
     * class ExampleListener :
     *                public virtual org::opensplice::domain::NoOpDomainParticipantListener
     * {
     *    // Not necessary to implement any Listener operations.
     * };
     * @endcode
     *
     * @see org::opensplice::domain::DomainParticipantListener
     */
    class NoOpDomainParticipantListener :
        public virtual dds::domain::NoOpDomainParticipantListener,
        public virtual org::opensplice::topic::NoOpAnyTopicListener
    { };

} /* namespace domain */




namespace core {
namespace status {

    /**
     * This object contains the statistics about the occurrence of the
     * ALL_DATA_DISPOSED_TOPIC_STATUS event on the Topic to which this Status is
     * attached. The Status is directly related to the invocation of the
     * dds::topic::AnyTopic::dispose_all_data operation. Statistics are only kept when all
     * instances are disposed using this operation, not when instances are disposed
     * seperately by individual dispose calls.
     */
    class AllDataDisposedTopicStatus : public dds::core::Value
    {
    public:
        /**
         * @return Total cumulative count of dispose all data events on the the Topic.
         */
        int32_t total_count() const
        {
            return this->delegate().total_count();
        }

        /**
         * @return The incremental number of dispose all data events since the last time the listener
         * was called or the status was read.
         */
        int32_t total_count_change() const
        {
            return this->delegate().total_count_change();
        }
    };

} /* namespace status */
} /* namespace core */




namespace core {
namespace policy {
    /**
     * A normal dispose results in an event. There is no sample accompinying the event.
     *
     * Although on the receiver side the event is processed correctly and the instance state
     * is modified accordingly, there is still a problem representing the event since there
     * is no valid sample accompanying it. That is why an event will always try to piggyback
     * on valid samples that still happen to be around in the reader.
     *
     * This InvalidSampleVisibility policy (proprietary part of the
     * dds::core::policy::ReaderDataLifecycle) is used to decide what to do when the instance
     * in question has no valid sample to piggyback the event.
     */
    struct InvalidSampleVisibility
    {
        enum Type
        {
            NO_INVALID_SAMPLES,      /**< In this case the event is lost, since there is no valid
                                      *   sample to piggyback on, and no invalid samples may be
                                      *   created to accompany the event.
                                      */
            MINIMUM_INVALID_SAMPLES, /**< This is the default setting. In this case one (and only
                                      *   one) invalid sample is created to piggyback all pending
                                      *   events on. The sample is only displayed once, and is
                                      *   then discarded. So even when you perform a read
                                      *   operation, the invalid sample will be consumed as
                                      *   soon as it is accessed.
                                      */
            ALL_INVALID_SAMPLES      /**< This is a new setting that we have envisaged, but not
                                      *   yet implemented. Currently it will throw an
                                      *   UnsupportedError. The idea is that when implemented,
                                      *   every event is represented by its own invalid sample.
                                      *   Keep in mind that invalid samples have no real content,
                                      *   and therefore do not consume resource limits. That
                                      *   means a KEEP_LAST reader with depth 1 can contain 1
                                      *   valid sample and any number of pending events. This
                                      *   allows you to see each event separately and removes
                                      *   the need to maintain administration for the last known
                                      *   dispose_count. Also since every event will have its own
                                      *   accompanying sample (even in case there are still valid
                                      *   samples around), each event will have a NOT_READ sample
                                      *   state which makes it easy to intercept with a single
                                      *   ReadCondition for NOT_READ data.
                                      */
        };
    };

    struct SchedulingKind
    {
        enum Type
        {
            SCHEDULE_DEFAULT,        /**< Underlying OS default scheduling.
                                      */
            SCHEDULE_TIMESHARING,    /**< Time-sharing scheduling (whether this is supported depends
                                      *   on the underlying OS).
                                      */
            SCHEDULE_REALTIME        /**< Real-time scheduling (whether this is supported depends
                                      *   on the underlying OS).
                                      */
        };
    };

    struct SchedulingPriorityKind
    {
        enum Type
        {
            PRIORITY_RELATIVE,       /**< The given scheduling priority for the thread (in
                                      *   org::opensplice::core::policy::Scheduling) is relative to the
                                      *   process priority.
                                      */
            PRIORITY_ABSOLUTE        /**< The given scheduling priority for the thread (in
                                      *   org::opensplice::core::policy::Scheduling) is an absolute
                                      *   value.
                                      */
        };
    };


    /**
     * @brief
     * QoS Policy to share a DataReader between multiple processes.
     *
     * This QosPolicy allows sharing of entities by multiple processes or threads. When
     * the policy is enabled, the data distribution service will try to look up an existing
     * entity that matches the name supplied in the Share QosPolicy. A new entity will only
     * be created if a shared entity registered under the specified name doesn’t exist yet.
     *
     * Shared Readers can be useful for implementing algorithms like the worker pattern,
     * where a single shared reader can contain samples representing different tasks that
     * may be processed in parallel by separate processes. In this algorithm each processes
     * consumes the task it is going to perform (i.e. it takes the sample representing that
     * task), thus preventing other processes from consuming and therefore performing the
     * same task.
     *
     * <b><i>Entities can only be shared between processes if OpenSplice is running in
     * federated mode, because it requires shared memory to communicate between the
     * different processes.</i></b>
     *
     * By default, the Share QosPolicy is not used and enable is FALSE. Name must be set
     * to a valid string for the Share QosPolicy to be valid when enable is set to TRUE.
     * This QosPolicy is applicable to DataReader and Subscriber entities, and cannot be
     * modified after the DataReader or Subscriber is enabled. Note that a DataReader can
     * only be shared if its Subscriber is also shared.
     */
    class Share : public dds::core::Value
    {
    public:
        /**
         * Creates a Share QoS Policy instance
         */
        Share();

        /**
         * Creates a Share QoS Policy instance
         *
         * @param name the name
         * @param enable state
         */
        Share(const std::string& name, bool enable);

        /**
         * Copies a Share QoS Policy instance
         *
         * @param other the Share QoS Policy instance to copy
         */
        Share(const Share& other);

    public:
        /**
         * Sets the name
         *
         * @param name the name
         */
        Share& name(const std::string& name);

        /**
         * Gets the name
         *
         * @return the name
         */
        std::string name() const;

        /**
         * Sets enable state
         *
         * @param enable state
         */
        Share& enable(bool enable);

        /**
         * Gets enable state
         *
         * @return enable state
         */
        bool enable() const;
    };


    /**
     * @brief
     * QoS Policy to for ProductData.
     *
     * This Policy is part of many proprietary builtin topics:
     * - org::opensplice::topic::CMParticipantBuiltinTopicData
     * - org::opensplice::topic::CMPublisherBuiltinTopicData
     * - org::opensplice::topic::CMSubscriberBuiltinTopicData
     * - org::opensplice::topic::CMDataWriterBuiltinTopicData
     * - org::opensplice::topic::CMDataReaderBuiltinTopicData
     *
     * The policy contains product information of the product that created
     * the related entity. The data will be formatted in XML. It is mostly
     * used by OpenSplice tools to display extended information about the
     * discovered entities.
     */
    class ProductData : public dds::core::Value
    {
    public:
        /**
         * Creates a ProductData QoS Policy instance
         */
        ProductData();

        /**
         * Creates a ProductData QoS Policy instance
         *
         * @param value the value
         */
        ProductData(const std::string& name);

        /**
         * Copies a ProductData QoS Policy instance
         *
         * @param other the ProductData QoS Policy instance to copy
         */
        ProductData(const ProductData& other);

    public:
        /**
         * Sets the name
         *
         * @param value the name
         */
        ProductData& name(const std::string& name);

        /**
         * Gets the name
         *
         * @return the name
         */
        std::string name() const;
    };

    /**
     * @brief
     * This QosPolicy allows the DataReader to define it's own set of keys on the data,
     * potentially different from the keys defined on the topic.
     *
     * By using the SubscriptionKey QosPolicy, a DataReader can force its own key-list
     * definition on data samples. The consequences are that the DataReader will
     * internally keep track of instances based on its own key list, instead of the key list
     * dictated by the Topic.
     *
     * Operations that operate on instances or instance handles, such as
     * lookup_instance or get_key_value, respect the alternative key-list and work
     * as expected. However, since the mapping of writer instances to reader instances is
     * no longer trivial (one writer instance may now map to more than one matching
     * reader instance and vice versa), a writer instance will no longer be able to fully
     * determine the lifecycle of its matching reader instance, nor the value its
     * view_state and instance_state.
     *
     * In fact, by diverting from the conceptual 1 – 1 mapping between writer instance and
     * reader instance, the writer can no longer keep an (empty) reader instance ALIVE by
     * just refusing to unregister its matching writer instance. That means that when a
     * reader takes all samples from a particular reader instance, that reader instance will
     * immediately be removed from the reader’s administration. Any subsequent
     * reception of a message with the same keys will re-introduce the instance into the
     * reader administration, setting its view_state back to NEW. Compare this to the
     * default behaviour, where the reader instance will be kept alive as long as the writer
     * does not unregister it. That causes the view_state in the reader instance to remain
     * NOT_NEW, even if the reader has consumed all of its samples prior to receiving an
     * update.
     *
     * Another consequence of allowing an alternative keylist is that events that are
     * communicated by invalid samples (i.e. samples that have only initialized their
     * keyfields) may no longer be interpreted by the reader to avoid situations in which
     * uninitialized non-keyfields are treated as keys in the alternative keylist. This
     * effectively means that all invalid samples (e.g. unregister messages and both
     * implicit and explicit dispose messages) will be skipped and can no longer affect the
     * instance_state, which will therefore remain ALIVE. The only exceptions to this
     * are the messages that are transmitted explicitly using the
     * dds::pub::DataWriter::writedispose call, which always includes a full and
     * valid sample and can therefore modify the instance_state to
     * NOT_ALIVE_DISPOSED.
     *
     * By default, the SubscriptionKeyQosPolicy is not used because use_key_list is
     * set to FALSE.
     *
     * This QosPolicy is applicable to a DataReader only, and cannot be changed after the
     * DataReader is enabled.
     */
    class SubscriptionKey : public dds::core::Value
    {
    public:
        /**
         * Creates a SubscriptionKey QoS Policy instance
         */
        SubscriptionKey();

        /**
         * Creates a SubscriptionKey QoS Policy instance
         *
         * @param use_key_list use the key list or not
         * @param key a single key
         */
        explicit SubscriptionKey(bool use_key_list, const std::string& key);

        /**
         * Creates a SubscriptionKey QoS Policy instance
         *
         * @param use_key_list use the key list or not
         * @param keys a sequence containing multiple keys
         */
        explicit SubscriptionKey(bool use_key_list, const dds::core::StringSeq& keys);

        /**
         * Copies a SubscriptionKey QoS Policy instance
         *
         * @param other the SubscriptionKey QoS Policy instance to copy
         */
        SubscriptionKey(const SubscriptionKey& other);

    public:
        /**
         * Sets the key
         *
         * @param key the key
         */
        SubscriptionKey& key(const std::string& key);

        /**
         * Sets multiple keys
         *
         * @param names a sequence containing multiple keys
         */
        SubscriptionKey& key(const dds::core::StringSeq& keys);

        /**
         * Gets the keys
         *
         * @return a sequence containing the keys
         */
        const dds::core::StringSeq key() const;

        /**
         * Sets use_key_list state
         *
         * @param use_key_list state
         */
        SubscriptionKey& use_key_list(bool use_key_list);

        /**
         * Gets use_key_list state
         *
         * @return use_key_list state
         */
        bool use_key_list() const;
    };

    /**
     * @brief
     * QoS Policy for automatically remove samples from the DataReader after
     * a specified timeout.
     *
     * This QosPolicy is similar to the Lifespan QosPolicy (applicable to Topic and
     * DataWriter), but limited to the DataReader on which the QosPolicy is applied. The
     * data is automatically removed from the DataReader if it has not been taken yet after
     * the lifespan duration expires. The duration of the ReaderLifespan is added to the
     * insertion time of the data in the DataReader to determine the expiry time.
     *
     * When both the ReaderLifespan QosPolicy and a DataWriter’s
     * Lifespan QosPolicy are applied to the same data, only the earliest expiry time is
     * taken into account.
     *
     * By default, the ReaderLifespan QosPolicy is not used and use_lifespan is FALSE.<br>
     * The duration is set to dds::core::Duration::infinite().
     *
     * This QosPolicy is applicable to a DataReader only, and is mutable even when the
     * DataReader is already enabled. If modified, the new setting will only be applied to
     * samples that are received after the modification took place.
     */
    class ReaderLifespan : public dds::core::Value
    {
    public:
        /**
         * Creates a ReaderLifespan QoS Policy instance
         */
        ReaderLifespan();

        /**
         * Creates a ReaderLifespan QoS Policy instance
         *
         * @param used Indicates ReaderLifespan is used
         * @param duration ReaderLifespan expiration duration
         */
        explicit ReaderLifespan(bool used, const dds::core::Duration& duration);

        /**
         * Copies a Lifespan QoS Policy instance
         *
         * @param other the Lifespan QoS instance to copy
         */
        ReaderLifespan(const ReaderLifespan& other);

    public:
        /**
         * Sets the used flag
         *
         * @param the used flag
         */
        ReaderLifespan& used(bool used);

        /**
         * Gets the used flag
         *
         * @return true if used
         */
        bool used() const;

        /**
         * Sets the expiration duration
         *
         * @param duration expiration duration
         */
        ReaderLifespan& duration(const dds::core::Duration& duration);

        /**
         * Gets the expiration duration
         *
         * @return expiration duration
         */
        const dds::core::Duration duration() const;
    };

    /**
     * @brief
     * QoS Policy base class for scheduling policies
     *
     * <b><i>Note that some scheduling parameters may
     * not be supported by the underlying Operating System, or that you may need special
     * privileges to select particular settings. Refer to the documentation of your OS for
     * more details on this subject.</i></b>
     *
     * Although the behaviour of the scheduling_class is highly dependent on the
     * underlying OS, in general it can be said that when running in a Timesharing class
     * your thread will have to yield execution to other threads of equal priority regularly.
     * In a Realtime class your thread normally runs until completion, and can only be
     * pre-empted by higher priority threads. Often the highest range of priorities is not
     * accessible through a Timesharing Class.
     *
     * The scheduling_priority_kind determines whether the specified
     * scheduling_priority should be interpreted as an absolute priority, or whether it
     * should be interpreted relative to the priority of its creator, in this case the priority of
     * the thread that created the DomainParticipant.
     */
    class Scheduling : public dds::core::Value
    {
    public:
        /**
         * Sets the scheduling kind
         *
         * @param scheduling_kind the scheduling_kind
         */
        Scheduling& scheduling_kind(const org::opensplice::core::policy::SchedulingKind::Type& scheduling_kind);

        /**
         * Gets the scheduling kind
         *
         * @return the scheduling_kind
         */
        org::opensplice::core::policy::SchedulingKind::Type scheduling_kind() const;

        /**
         * Sets the scheduling priority kind
         *
         * @param scheduling_priority_kind the scheduling_priority_kind
         */
        Scheduling& scheduling_kind(const org::opensplice::core::policy::SchedulingPriorityKind::Type& scheduling_priority_kind);

        /**
         * Gets the scheduling priority kind
         *
         * @return the scheduling_priority_kind
         */
        org::opensplice::core::policy::SchedulingPriorityKind::Type scheduling_priority_kind() const;

        /**
         * Sets the scheduling priority
         *
         * @param scheduling_priority the scheduling_priority
         */
        Scheduling& scheduling_priority(int32_t scheduling_priority);

        /**
         * Gets the scheduling priority
         *
         * @return the scheduling_priority
         */
        int32_t scheduling_priority() const;
    };

    /**
     * @brief
     * This QosPolicy specifies the scheduling parameters that will be used for
     * the Listener thread that is spawned by the DomainParticipant.
     *
     * @see org::opensplice::core::policy::Scheduling for scheduling information.
     */
    class ListenerScheduling : public org::opensplice::core::policy::Scheduling
    {
    public:
        /**
         * Creates a ListenerScheduling QoS instance
         */
        ListenerScheduling();

        /**
         * Creates a ListenerScheduling QoS instance
         *
         * @param scheduling_kind
         *              Specifies the scheduling class used by the Operating System, which may be
         *              SCHEDULE_DEFAULT, SCHEDULE_TIMESHARING or SCHEDULE_REALTIME.
         *              Threads can only be spawned within the scheduling classes that are supported
         *              by the underlying Operating System.
         * @param scheduling_priority_kind
         *              Specifies the priority type, which may be either PRIORITY_RELATIVE or
         *              PRIORITY_ABSOLUTE.
         * @param scheduling_priority
         *              Specifies the priority that will be assigned to threads
         *              spawned by the DomainParticipant. Threads can only be spawned with
         *              priorities that are supported by the underlying Operating System.
         */
        explicit ListenerScheduling(const org::opensplice::core::policy::SchedulingKind::Type& scheduling_kind,
                                    const org::opensplice::core::policy::SchedulingPriorityKind::Type& scheduling_priority_kind,
                                    int32_t scheduling_priority);

        /**
         * Copies a ListenerScheduling QoS instance
         *
         * @param other the ListenerScheduling QoS instance to copy
         */
        ListenerScheduling(const ListenerScheduling& other);
    };

    /**
     * @brief
     * This QosPolicy specifies the scheduling parameters that will be used for
     * the Watchdog thread that is spawned by the DomainParticipant.
     *
     * @see org::opensplice::core::policy::Scheduling for scheduling information.
     */
    class WatchdogScheduling : public org::opensplice::core::policy::Scheduling
    {
    public:
        /**
         * Creates a WatchdogScheduling QoS instance
         */
        WatchdogScheduling();

        /**
         * Creates a WatchdogScheduling QoS instance
         *
         * @param scheduling_kind
         *              Specifies the scheduling class used by the Operating System, which may be
         *              SCHEDULE_DEFAULT, SCHEDULE_TIMESHARING or SCHEDULE_REALTIME.
         *              Threads can only be spawned within the scheduling classes that are supported
         *              by the underlying Operating System.
         * @param scheduling_priority_kind
         *              Specifies the priority type, which may be either PRIORITY_RELATIVE or
         *              PRIORITY_ABSOLUTE.
         * @param scheduling_priority
         *              Specifies the priority that will be assigned to threads
         *              spawned by the DomainParticipant. Threads can only be spawned with
         *              priorities that are supported by the underlying Operating System.
         */
        explicit WatchdogScheduling(const org::opensplice::core::policy::SchedulingKind::Type& scheduling_kind,
                                    const org::opensplice::core::policy::SchedulingPriorityKind::Type& scheduling_priority_kind,
                                    int32_t scheduling_priority);

        /**
         * Copies a WatchdogScheduling QoS instance
         *
         * @param other the WatchdogScheduling QoS instance to copy
         */
        WatchdogScheduling(const WatchdogScheduling& other);
    };

} /* namespace policy */
} /* namespace core */


} /* namespace opensplice */
} /* namespace org */

#endif /* DOXYGEN_FOR_ISOCPP2 */

#endif /* OMG_DDS_CORE_DETAIL_PROPRIETARY_API_HPP_ */



