public static boolean isEligibleForCarbonsDelivery(final Message stanza)
    {
        // To properly handle messages exchanged with a MUC (or similar service), the server must be able to identify MUC-related messages.
        // This can be accomplished by tracking the clients' presence in MUCs, or by checking for the <x xmlns="http://jabber.org/protocol/muc#user">
        // element in messages. The following rules apply to MUC-related messages:
        if (stanza.getChildElement("x", "http://jabber.org/protocol/muc#user") != null)
        {
            // A <message/> containing a Direct MUC Invitations (XEP-0249) SHOULD be carbon-copied.
            if (containsChildElement(stanza, Set.of("x"), "jabber:x:conference")) {
                return true;
            }

            // A <message/> containing a Mediated Invitation SHOULD be carbon-copied.
            if (stanza.getChildElement("x", "http://jabber.org/protocol/muc#user") != null
                && stanza.getChildElement("x", "http://jabber.org/protocol/muc#user").element("invite") != null) {
                return true;
            }

            // A private <message/> from a local user to a MUC participant (sent to a full JID) SHOULD be carbon-copied
            // The server SHOULD limit carbon-copying to the clients sharing a Multi-Session Nick in that MUC, and MAY
            // inject the <x/> element into such carbon copies. Clients can not respond to carbon-copies of MUC-PMs
            // related to a MUC they are not joined to. Therefore, they SHOULD either ignore such carbon copies, or
            // provide a way for the user to join the MUC before answering.
            if (stanza.getTo() != null && stanza.getTo().getResource() != null
                && stanza.getFrom() != null && stanza.getFrom().getNode() != null && XMPPServer.getInstance().isLocal(stanza.getFrom()))
            {
                return true;
                // TODO The server SHOULD limit carbon-copying to the clients sharing a Multi-Session Nick in that MUC (OF-2780).
            }

            // A private <message/> from a MUC participant (received from a full JID) to a local user SHOULD NOT be
            // carbon-copied (these messages are already replicated by the MUC service to all joined client instances).
            if (stanza.getFrom() != null && stanza.getFrom().getResource() != null
                && stanza.getTo() != null && stanza.getTo().getNode() != null && XMPPServer.getInstance().isLocal(stanza.getTo()))
            {
                return false;
            }
        }

        // A <message/> of type "groupchat" SHOULD NOT be carbon-copied.
        if (stanza.getType() == Message.Type.groupchat) {
            return false;
        }

        // A <message/> is eligible for carbons delivery if it does not contain a <private/> child element...
        if (containsChildElement(stanza, Set.of("private", "received"), "urn:xmpp:carbons"))
        {
            return false;
        }

        // and if at least one of the following is true:

        // ... it is of type "chat".
        if (stanza.getType() == Message.Type.chat) {
            return true;
        }

        // ... it is of type "normal" and contains a <body> element.
        if ((stanza.getType() == null || stanza.getType() == Message.Type.normal) && stanza.getBody() != null) {
            return true;
        }

        // ... it contains payload elements typically used in IM
        if (containsChildElement(stanza, Set.of("request", "received"), "urn:xmpp:receipts") // Message Delivery Receipts (XEP-0184)
         || containsChildElement(stanza, Set.of("active", "inactive", "gone", "composing", "paused"), "http://jabber.org/protocol/chatstates") // Chat State Notifications (XEP-0085)
         || (containsChildElement(stanza, Set.of("markable", "received", "displayed", "acknowledged"), "urn:xmpp:chat-markers"))  // Chat Markers (XEP-0333)).
        ) {
            return true;
        }

        // ... it is of type "error" and it was sent in response to a <message/> that was eligible for carbons delivery.
        // TODO implement me (OF-2779)

        return false;
    }
@Test
    public void testChatPrivate() throws Exception
    {
        // Setup test fixture.
        final Message input = new Message();
        input.setType(Message.Type.chat);
        input.getElement().addElement("private", "urn:xmpp:carbons:2");

        // Execute system under test.
        final boolean result = Forwarded.isEligibleForCarbonsDelivery(input);

        // Verify results.
        assertFalse(result);
    }