1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-06-13 23:24:50 +02:00
Smack/smack-experimental/src/main/java/org/jivesoftware/smackx/message_retraction/MessageRetractionManager.java
Florian Schmaus 3d4e7938a7 Make ExtensionElement marker interface wrt. QNAME field
ExtensionElement is now a marker interface that requires all
implementation non-abstract classes to carry a static final QNAME
field (of type QName). This is verified by a new unit test.

Also FullyQualifiedElement is renamed to simply XmlElement. XmlElement
is used over ExtensionElement when implementing classes do not
statically know the qualified name of the XML elements they
represent. In general, XmlElement should be used sparingly, and every
XML element should be modeled by its own Java class (implementing
ExtensionElement).
2021-04-18 21:07:19 +02:00

130 lines
5.2 KiB
Java

/**
*
* Copyright 2020 Paul Schaub
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.message_retraction;
import java.util.Map;
import java.util.WeakHashMap;
import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPConnectionRegistry;
import org.jivesoftware.smack.packet.MessageBuilder;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.message_fastening.element.FasteningElement;
import org.jivesoftware.smackx.message_retraction.element.RetractElement;
import org.jivesoftware.smackx.sid.element.OriginIdElement;
/**
* Smacks API for XEP-0424: Message Retraction.
*
* To enable / disable auto-announcing support for this feature, call {@link #setEnabledByDefault(boolean)}.
* Auto-announcing is enabled by default.
*
* To retract a message, call {@link #retractMessage(OriginIdElement)}, passing in the {@link OriginIdElement Origin ID}
* of the message to be retracted.
*/
public final class MessageRetractionManager extends Manager {
private static final Map<XMPPConnection, MessageRetractionManager> INSTANCES = new WeakHashMap<>();
private static boolean ENABLED_BY_DEFAULT = false;
static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
@Override
public void connectionCreated(XMPPConnection connection) {
if (ENABLED_BY_DEFAULT) {
getInstanceFor(connection).announceSupport();
}
}
});
}
private MessageRetractionManager(XMPPConnection connection) {
super(connection);
}
public static synchronized MessageRetractionManager getInstanceFor(XMPPConnection connection) {
MessageRetractionManager manager = INSTANCES.get(connection);
if (manager == null) {
manager = new MessageRetractionManager(connection);
INSTANCES.put(connection, manager);
}
return manager;
}
/**
* Enable or disable auto-announcing support for Message Retraction.
* Default is disabled.
*
* @param enabled enabled
*/
public static synchronized void setEnabledByDefault(boolean enabled) {
ENABLED_BY_DEFAULT = enabled;
}
/**
* Announce support for Message Retraction to the server.
*
* @see <a href="https://xmpp.org/extensions/xep-0424.html#disco">XEP-0424: Message Retraction: §2. Discovering Support</a>
*/
public void announceSupport() {
ServiceDiscoveryManager.getInstanceFor(connection()).addFeature(RetractElement.NAMESPACE);
}
/**
* Stop announcing support for Message Retraction.
*/
public void stopAnnouncingSupport() {
ServiceDiscoveryManager.getInstanceFor(connection()).removeFeature(RetractElement.NAMESPACE);
}
/**
* Append a {@link RetractElement} wrapped inside a {@link FasteningElement} which contains
* the {@link OriginIdElement Origin-ID} of the message that will be retracted to the given {@link MessageBuilder}.
*
* @param retractedMessageId {@link OriginIdElement OriginID} of the message that the user wants to retract
* @param carrierMessageBuilder message used to transmit the message retraction to the recipient
*/
public static void addRetractionElementToMessage(OriginIdElement retractedMessageId, MessageBuilder carrierMessageBuilder) {
FasteningElement fasteningElement = FasteningElement.builder()
.setOriginId(retractedMessageId)
.addWrappedPayload(new RetractElement())
.build();
fasteningElement.applyTo(carrierMessageBuilder);
}
/**
* Retract a message by appending a {@link RetractElement} wrapped inside a {@link FasteningElement} which contains
* the {@link OriginIdElement Origin-ID} of the message that will be retracted to a new message and send it to the
* server.
*
* @param retractedMessageId {@link OriginIdElement OriginID} of the message that the user wants to retract
* @throws SmackException.NotConnectedException in case the connection is not connected.
* @throws InterruptedException if the thread gets interrupted.
*/
public void retractMessage(OriginIdElement retractedMessageId)
throws SmackException.NotConnectedException, InterruptedException {
MessageBuilder message = connection().getStanzaFactory().buildMessageStanza();
addRetractionElementToMessage(retractedMessageId, message);
connection().sendStanza(message.build());
}
}