001/** 002 * 003 * Copyright 2018 Paul Schaub, 2020 Florian Schmaus. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jivesoftware.smackx.mood; 018 019import java.util.Map; 020import java.util.WeakHashMap; 021 022import org.jivesoftware.smack.Manager; 023import org.jivesoftware.smack.SmackException; 024import org.jivesoftware.smack.XMPPConnection; 025import org.jivesoftware.smack.XMPPException; 026import org.jivesoftware.smack.packet.Message; 027import org.jivesoftware.smack.provider.ProviderManager; 028 029import org.jivesoftware.smackx.mood.element.MoodConcretisation; 030import org.jivesoftware.smackx.mood.element.MoodElement; 031import org.jivesoftware.smackx.mood.provider.MoodConcretisationProvider; 032import org.jivesoftware.smackx.pep.PepEventListener; 033import org.jivesoftware.smackx.pep.PepManager; 034import org.jivesoftware.smackx.pubsub.PayloadItem; 035import org.jivesoftware.smackx.pubsub.PubSubException; 036 037/** 038 * Entry point for Smacks API for XEP-0107: User Mood. 039 * 040 * To set a mood, please use one of the {@link #setMood(Mood)} methods. This will publish the users mood to a pubsub 041 * node.<br> 042 * <br> 043 * In order to get updated about other users moods, register a {@link PepEventListener} at 044 * {@link #addMoodListener(PepEventListener)}. That listener will get updated about any incoming mood updates of contacts.<br> 045 * <br> 046 * To stop publishing the users mood, refer to {@link #clearMood()}.<br> 047 * <br> 048 * It is also possible to add {@link MoodElement}s to {@link Message}s by using {@link #addMoodToMessage(Message, Mood)}.<br> 049 * <br> 050 * The API can be extended with custom mood concretisations by extending {@link MoodConcretisation} and registering 051 * {@link MoodConcretisationProvider}s using {@link ProviderManager#addExtensionProvider(String, String, Object)}.<br> 052 * An example of how this can be done can be found in the MoodConcretisationTest in the test package. 053 * 054 * @see <a href="https://xmpp.org/extensions/xep-0107.html"> 055 * XEP-0107: User Mood</a> 056 */ 057public final class MoodManager extends Manager { 058 059 public static final String MOOD_NODE = "http://jabber.org/protocol/mood"; 060 061 private static final Map<XMPPConnection, MoodManager> INSTANCES = new WeakHashMap<>(); 062 063 private final PepManager pepManager; 064 065 private MoodManager(XMPPConnection connection) { 066 super(connection); 067 068 pepManager = PepManager.getInstanceFor(connection); 069 } 070 071 public static synchronized MoodManager getInstanceFor(XMPPConnection connection) { 072 MoodManager manager = INSTANCES.get(connection); 073 if (manager == null) { 074 manager = new MoodManager(connection); 075 INSTANCES.put(connection, manager); 076 } 077 return manager; 078 } 079 080 public void setMood(Mood mood) 081 throws InterruptedException, SmackException.NotLoggedInException, SmackException.NoResponseException, 082 SmackException.NotConnectedException, XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException { 083 setMood(mood, null, null); 084 } 085 086 public void setMood(Mood mood, String text) 087 throws InterruptedException, SmackException.NotLoggedInException, SmackException.NoResponseException, 088 SmackException.NotConnectedException, XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException { 089 setMood(mood, null, text); 090 } 091 092 public void setMood(Mood mood, MoodConcretisation concretisation) 093 throws InterruptedException, SmackException.NotLoggedInException, SmackException.NoResponseException, 094 SmackException.NotConnectedException, XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException { 095 setMood(mood, concretisation, null); 096 } 097 098 public void setMood(Mood mood, MoodConcretisation concretisation, String text) 099 throws InterruptedException, SmackException.NotLoggedInException, SmackException.NoResponseException, 100 SmackException.NotConnectedException, XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException { 101 MoodElement element = buildMood(mood, concretisation, text); 102 publishMood(element); 103 } 104 105 public void clearMood() 106 throws InterruptedException, SmackException.NotLoggedInException, SmackException.NoResponseException, 107 SmackException.NotConnectedException, XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException { 108 MoodElement element = buildMood(null, null, null); 109 publishMood(element); 110 } 111 112 private void publishMood(MoodElement moodElement) 113 throws SmackException.NotLoggedInException, InterruptedException, PubSubException.NotALeafNodeException, 114 XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException { 115 pepManager.publish(MOOD_NODE, new PayloadItem<>(moodElement)); 116 } 117 118 private static MoodElement buildMood(Mood mood, MoodConcretisation concretisation, String text) { 119 return new MoodElement( 120 new MoodElement.MoodSubjectElement(mood, concretisation), 121 text); 122 } 123 124 public static void addMoodToMessage(Message message, Mood mood) { 125 addMoodToMessage(message, mood, null); 126 } 127 128 public static void addMoodToMessage(Message message, Mood mood, MoodConcretisation concretisation) { 129 MoodElement element = buildMood(mood, concretisation, null); 130 message.addExtension(element); 131 } 132 133 public boolean addMoodListener(PepEventListener<MoodElement> listener) { 134 return pepManager.addPepEventListener(MOOD_NODE, MoodElement.class, listener); 135 } 136 137 public boolean removeMoodListener(PepEventListener<MoodElement> listener) { 138 return pepManager.removePepEventListener(listener); 139 } 140}