########################################################################
# 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"
[docs]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
 
[docs]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,
    )
    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
[docs]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
[docs]class RosterVersioningFeature(xso.XSO):
    """
    Roster versioning feature.
    .. seealso::
       :class:`aioxmpp.nonza.StreamFeatures`
    """
    TAG = (namespaces.rfc6121_roster_versioning, "ver")