private Future<?> subscribeNode(final PubSubService service, final IQ iq, final Element childElement, Element subscribeElement) {
        String nodeID = subscribeElement.attributeValue("node");
        final Node node;
        if (nodeID == null) {
            if (service.isCollectionNodesSupported()) {
                // Entity subscribes to root collection node
                node = service.getRootCollectionNode();
            }
            else {
                // Service does not have a root collection node so return a nodeid-required error
                Element pubsubError = DocumentHelper.createElement(QName.get(
                        "nodeid-required", "http://jabber.org/protocol/pubsub#errors"));
                sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError);
                return new ImmediateFuture<>();
            }
        }
        else {
            // Look for the specified node
            node = service.getNode(nodeID);
            if (node == null) {
                // Node does not exist. Return item-not-found error
                sendErrorPacket(iq, PacketError.Condition.item_not_found, null);
                return new ImmediateFuture<>();
            }
        }
        // Check if sender and subscriber JIDs match or if a valid "trusted proxy" is being used
        final JID from = iq.getFrom();
        final JID subscriberJID = new JID(subscribeElement.attributeValue("jid"));
        if (!from.toBareJID().equals(subscriberJID.toBareJID()) && !service.isServiceAdmin(from)) {
            // JIDs do not match and requestor is not a service admin so return an error
            Element pubsubError = DocumentHelper.createElement(
                    QName.get("invalid-jid", "http://jabber.org/protocol/pubsub#errors"));
            sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError);
            return new ImmediateFuture<>();
        }
        // TODO Assumed that the owner of the subscription is the bare JID of the subscription JID. Waiting StPeter answer for explicit field.
        final JID owner = subscriberJID.asBareJID();
        // Check if the node's access model allows the subscription to proceed
        final AccessModel accessModel = node.getAccessModel();
        if (!accessModel.canSubscribe(node, owner, subscriberJID)) {
            sendErrorPacket(iq, accessModel.getSubsriptionError(),
                    accessModel.getSubsriptionErrorDetail());
            return new ImmediateFuture<>();
        }

        // Complete this asynchronously, as UserManager::isRegisteredUser(JID) blocks, waiting for a result which may come in on this thread
        return TaskEngine.getInstance().submit(() -> subscribeNodeAsync(iq, subscriberJID, node, owner, service, from, childElement, accessModel));
    }
Checks of the configuration of the node meets the preconditions, as supplied in the dataform.

This method returns true only if the configuration of the node at least contains each of the fields
defined in the preconditions (with matching values).

@param node The node (cannot be null)
@param preconditions The preconditions (can be null, in which case 'true' is returned).
@return True if all preconditions are met, otherwise false.
xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/PubSubEngine.java