# Source code for aioxmpp.roster.xso

    ########################################################################
    # File name: xso.py
    # This file is part of: aioxmpp
    #
    # LICENSE
    #
    # This program is free software: you can redistribute it and/or modify
    # it under the terms of the GNU Lesser General Public License as
    # published by the Free Software Foundation, either version 3 of the
    # License, or (at your option) any later version.
    #
    # This program 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 program.  If not, see
    # <http://www.gnu.org/licenses/>.
    #
    ########################################################################
    import aioxmpp.stanza as stanza
    import aioxmpp.nonza as nonza
    import aioxmpp.xso as xso

    from aioxmpp.utils import namespaces

    namespaces.rfc6121_roster = "jabber:iq:roster"
    namespaces.rfc6121_roster_versioning = "urn:xmpp:features:rosterver"

    class Group(xso.XSO):
        """
        A group declaration for a contact in a roster.

        .. attribute:: name

           The name of the group.

        """
        TAG = (namespaces.rfc6121_roster, "group")

        name = xso.Text(default=None)

        def __init__(self, *, name=None):
            super().__init__()
            self.name = name

    class Item(xso.XSO):
        """
        A contact item in a roster.

        .. attribute:: jid

           The bare :class:`~aioxmpp.JID of the contact.

        .. attribute:: name

           The optional display name of the contact.

        .. attribute:: groups

           A :class:`~aioxmpp.xso.model.XSOList` of :class:`Group` instances which
           describe the roster groups in which the contact is.

        The following attributes represent the subscription status of the
        contact. A client **must not** set these attributes when sending roster
        items to the server. To change subscription status, use presence stanzas of
        the respective type. The only exception is a :attr:`subscription` value of
        ``"remove"``, which is used to remove an entry from the roster.

        .. attribute:: subscription

           Primary subscription status, one of ``"none"`` (the default), ``"to"``,
           ``"from"`` and ``"both"``.

           In addition, :attr:`subscription` can be set to ``"remove"`` to remove
           an item from the roster during a roster set. Removing an entry from the
           roster will also cancel any presence subscriptions from and to that
           entries entity.

        .. attribute:: approved

           Whether the subscription has been pre-approved by the owning entity.

        .. attribute:: ask

           Subscription sub-states, one of ``"subscribe"`` and :data:`None`.

        .. note::

           Do not confuse this class with :class:`~aioxmpp.roster.Item`.

        """

        TAG = (namespaces.rfc6121_roster, "item")

        approved = xso.Attr(
            "approved",
            type_=xso.Bool(),
            default=False,
        )

        ask = xso.Attr(
            "ask",
            validator=xso.RestrictToSet({
                None,
                "subscribe",
            }),
            validate=xso.ValidateMode.ALWAYS,
            default=None,
        )

        jid = xso.Attr(
            "jid",
            type_=xso.JID(),
        )

        name = xso.Attr(
            "name",
            default=None,
        )

        subscription = xso.Attr(
            "subscription",
            validator=xso.RestrictToSet({
                "none",
                "to",
                "from",
                "both",
                "remove",
            }),
            validate=xso.ValidateMode.ALWAYS,
            default="none",
        )

        groups = xso.ChildList([Group])

        def __init__(self, jid, *,
                     name=None,
                     groups=(),
                     subscription="none",
                     approved=False,
                     ask=None):
            super().__init__()
            if jid is not None:
                self.jid = jid
            self.name = name
            self.groups.extend(groups)
            self.subscription = subscription
            self.approved = approved
            self.ask = ask

    @stanza.IQ.as_payload_class
    class Query(xso.XSO):
        """
        A query which fetches data from the roster or sends new items to the
        roster.

        .. attribute:: ver

           The version of the roster, if any. See the RFC for the detailed
           semantics.

        .. attribute:: items

           The items in the roster query.

        """
        TAG = (namespaces.rfc6121_roster, "query")

        ver = xso.Attr(
            "ver",
            default=None
        )

        items = xso.ChildList([Item])

        def __init__(self, *, ver=None, items=()):
            super().__init__()
            self.ver = ver
            self.items.extend(items)

    @nonza.StreamFeatures.as_feature_class
    class RosterVersioningFeature(xso.XSO):
        """
        Roster versioning feature.

        .. seealso::

           :class:`aioxmpp.nonza.StreamFeatures`

        """
        TAG = (namespaces.rfc6121_roster_versioning, "ver")