private Stanza handleOutboundUnavailable()

in server/core/src/main/java/org/apache/vysper/xmpp/modules/core/im/handler/PresenceAvailabilityHandler.java [152:221]


    private Stanza handleOutboundUnavailable(PresenceStanza presenceStanza, SessionContext sessionContext,
            RosterManager rosterManager, Entity user, ResourceRegistry registry, StanzaBroker stanzaBroker) {

        boolean hasTo = presenceStanza.getCoreVerifier().attributePresent("to");
        if (hasTo)
            return handleOutboundDirectedPresence(presenceStanza, sessionContext, rosterManager, registry, true,
                    stanzaBroker);

        if (!user.isResourceSet())
            throw new RuntimeException("resource id not available");
        boolean stateChanged = registry.setResourceState(user.getResource(), ResourceState.UNAVAILABLE);
        // avoid races from closing connections and unavail presence stanza handlings
        // happening quasi-concurrently
        if (!stateChanged)
            return null;

        sessionContext.getServerRuntimeContext().getPresenceCache().remove(user);

        SessionContext.SessionTerminationCause terminationCause = null;
        if (presenceStanza instanceof EndOfSessionCommandStanza) {
            EndOfSessionCommandStanza commandStanza = (EndOfSessionCommandStanza) presenceStanza;
            terminationCause = commandStanza.getSessionTerminationCause();
        }

        // TODO check if we do have to do something about resource priority

        List<Entity> contacts = new ArrayList<Entity>();

        Map<SubscriptionType, List<RosterItem>> itemMap = RosterUtils.getRosterItemsByState(rosterManager, user);
        List<RosterItem> item_FROM = itemMap.get(SubscriptionType.FROM);
        List<RosterItem> item_TO = itemMap.get(SubscriptionType.TO);
        List<RosterItem> item_BOTH = itemMap.get(SubscriptionType.BOTH);

        // broadcast presence from full JID to contacts
        // in roster with 'subscription' either 'from' or 'both'
        // TODO (for pres updates): ...and last presence stanza received from the
        // contact during the user's
        // presence session was not of type "error" or "unsubscribe".

        List<RosterItem> rosterContacts_FROM = new ArrayList<RosterItem>();
        rosterContacts_FROM.addAll(item_FROM);
        rosterContacts_FROM.addAll(item_BOTH);
        for (RosterItem rosterContact : rosterContacts_FROM) {
            contacts.add(rosterContact.getJid());
        }

        // broadcast unavailable to all directed-presence contacts
        Set<Entity> entitySet = getDirectedPresenceMap(sessionContext, user);
        if (entitySet != null) {
            logger.debug("sending unavailable info to " + entitySet.size() + " directed presence contacts for " + user);
            contacts.addAll(entitySet);
            entitySet.clear(); // and un-record them
        }

        // broadcast presence notification to all resources of
        // current entity.
        List<String> resources = registry.getAvailableResources(user);
        if (!SessionContext.SessionTerminationCause.isClientReceivingStanzas(terminationCause)) {
            resources.remove(user.getResource());
        }
        for (String resource : resources) {
            Entity otherResource = new EntityImpl(user, resource);
            contacts.add(otherResource);
        }

        // and send them out
        relayTo(user, contacts, presenceStanza, stanzaBroker);

        return null;
    }