private PresenceStanza handleOutboundAvailable()

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


    private PresenceStanza handleOutboundAvailable(PresenceStanza presenceStanza,
            ServerRuntimeContext serverRuntimeContext, SessionContext sessionContext, RosterManager rosterManager,
            Entity user, ResourceRegistry registry, StanzaBroker stanzaBroker) {
        boolean hasTo = presenceStanza.getCoreVerifier().attributePresent("to");
        if (hasTo)
            return handleOutboundDirectedPresence(presenceStanza, sessionContext, rosterManager, registry, false,
                    stanzaBroker);

        if (!user.isResourceSet())
            throw new RuntimeException("resource id not available");
        String resourceId = user.getResource();
        ResourceState resourceState = registry.getResourceState(resourceId);

        boolean isPresenceUpdate = resourceState != null && ResourceState.isAvailable(resourceState);

        // TODO in case of !isPresenceUpdate, should we check for resourceState !=
        // ResourceState.AVAILABLE_INTERESTED ?
        // RFC3921bis-04#4.2.2 Initial Presence
        // RFC3921bis-04#4.4.2 Initial Presence

        updateLatestPresence(sessionContext, user, presenceStanza);
        if (!isPresenceUpdate) {
            // things to be done for initial presence

            // set resource state
            ResourceState currentState = registry.getResourceState(resourceId);
            // set to AVAILABLE, but do not override AVAILABLE_INTERESTED
            registry.setResourceState(resourceId, ResourceState.makeAvailable(currentState));
        }

        // the presence priority is optional, but if contained, it might become relevant
        // for
        // message delivery (see RFC3921bis-05#8.3.1.1)
        registry.setResourcePriority(resourceId, presenceStanza.getPrioritySafe());

        // check for pending offline stored stanzas, and send them out
        OfflineStorageProvider offlineProvider = serverRuntimeContext.getStorageProvider(OfflineStorageProvider.class);
        if (offlineProvider == null) {
            logger.warn("No Offline Storage Provider configured");
        } else {
            Collection<Stanza> offlineStanzas = offlineProvider.getStanzasFor(user);
            for (Stanza stanza : offlineStanzas) {
                logger.debug("Sending out delayed offline stanza");
                stanzaBroker.writeToSession(stanza);
            }
        }

        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: ...and user is not blocking outbound presence notifications above
        // 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 presence notification to all resources of
        // current entity.
        List<String> resources = registry.getAvailableResources(user);
        for (String resource : resources) {
            Entity otherResource = new EntityImpl(user, resource);
            contacts.add(otherResource);
        }

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

        if (!isPresenceUpdate) {
            // initial presence only:
            // send probes to all contacts of the current jid where
            // 'subscription' is either 'to' or 'both'
            // TODO: ...and jid is not blocking inbound presence notification
            // TODO: optimize: don't send server-local probes when contact's presence is
            // known locally
            List<RosterItem> rosterContacts_TO = new ArrayList<RosterItem>();
            rosterContacts_TO.addAll(item_TO);
            rosterContacts_TO.addAll(item_BOTH);
            for (RosterItem rosterItem : rosterContacts_TO) {
                Entity contact_TO = rosterItem.getJid();
                Stanza probeStanza = buildPresenceStanza(user, contact_TO, PresenceStanzaType.PROBE, null);
                relayStanza(contact_TO, probeStanza, stanzaBroker);
            }
        }

        return null;
    }