You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

XmppClientInfo.java 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * Copyright (c) 2006-2017 DMDirc Developers
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. * SOFTWARE.
  21. */
  22. package com.dmdirc.parser.xmpp;
  23. import com.dmdirc.parser.common.AwayState;
  24. import com.dmdirc.parser.common.BaseClientInfo;
  25. import com.dmdirc.parser.interfaces.ChannelClientInfo;
  26. import com.google.common.collect.Lists;
  27. import java.util.ArrayList;
  28. import java.util.Collections;
  29. import java.util.HashMap;
  30. import java.util.HashSet;
  31. import java.util.List;
  32. import java.util.Map;
  33. import java.util.Set;
  34. import org.jivesoftware.smack.RosterEntry;
  35. import org.jivesoftware.smack.packet.Presence;
  36. import org.jivesoftware.smack.packet.Presence.Mode;
  37. import org.jivesoftware.smack.packet.Presence.Type;
  38. /**
  39. * An XMPP-specific client info object.
  40. */
  41. public class XmppClientInfo extends BaseClientInfo {
  42. /** A map of known endpoints for this client. */
  43. private final Map<String, XmppEndpoint> endpoints = new HashMap<>();
  44. /**
  45. * Creates a new XMPP Client Info object with the specified details.
  46. *
  47. * @param parser The parser that owns this client info object
  48. * @param nick The nickname of the user this object represents
  49. * @param user The username of the user this object represents
  50. * @param host The hostname of the user this object represents
  51. */
  52. public XmppClientInfo(final XmppParser parser, final String nick, final String user,
  53. final String host) {
  54. super(parser, nick, user, host);
  55. }
  56. @Override
  57. public int getChannelCount() {
  58. return 0;
  59. }
  60. @Override
  61. public List<ChannelClientInfo> getChannelClients() {
  62. return Lists.newArrayList();
  63. }
  64. /**
  65. * Retrieves the map of known endpoints for this client.
  66. *
  67. * @return A map of endpoint names to presence states.
  68. */
  69. public Map<String, XmppEndpoint> getEndpoints() {
  70. return Collections.unmodifiableMap(endpoints);
  71. }
  72. /**
  73. * Sets the presence of one endpoint of this client.
  74. *
  75. * @param packet The presence packet received
  76. */
  77. public void setPresence(final Presence packet) {
  78. final String[] parts = getParser().parseHostmask(packet.getFrom());
  79. final boolean wasAway = isAway();
  80. if (packet.getType() == Type.unavailable) {
  81. endpoints.remove(parts[1]);
  82. } else {
  83. if (!endpoints.containsKey(parts[1])) {
  84. endpoints.put(parts[1], new XmppEndpoint());
  85. }
  86. final XmppEndpoint endpoint = endpoints.get(parts[1]);
  87. endpoint.setPriority(packet.getPriority());
  88. endpoint.setMode(packet.getMode());
  89. endpoint.setType(packet.getType());
  90. endpoint.setStatus(packet.getStatus());
  91. }
  92. final boolean isAway = isAway();
  93. if (wasAway != isAway) {
  94. // Their away status has changed
  95. getParser().handleAwayStateChange(this, wasAway);
  96. }
  97. }
  98. /**
  99. * Determines whether or not this contact is "away" - that is, their aggregate presence state is
  100. * "Unavailable", "Away", "DND" or "XA".
  101. *
  102. * @return True if the client is away, false otherwise
  103. */
  104. public boolean isAway() {
  105. final Mode presence = getAggregatePresence();
  106. return presence == null || presence.compareTo(Mode.away) >= 0;
  107. }
  108. @Override
  109. public AwayState getAwayState() {
  110. return isAway() ? AwayState.AWAY : AwayState.HERE;
  111. }
  112. /**
  113. * Gets the aggregate presence of this contact.
  114. *
  115. * @return The highest available state of the contact's highest priority endpoints, * or
  116. * <code>null</code> if no endpoints are available.
  117. */
  118. public Mode getAggregatePresence() {
  119. final List<XmppEndpoint> sortedEndpoints = new ArrayList<>(endpoints.values());
  120. Collections.sort(sortedEndpoints);
  121. // Get the set of the highest priority endpoints
  122. final Set<XmppEndpoint> bestEndpoints = new HashSet<>(sortedEndpoints.size());
  123. int best = 0;
  124. for (XmppEndpoint endpoint : sortedEndpoints) {
  125. if (endpoint.getType() != Type.available) {
  126. continue;
  127. }
  128. if (bestEndpoints.isEmpty()) {
  129. best = endpoint.getPriority();
  130. }
  131. if (endpoint.getPriority() == best && best >= 0) {
  132. bestEndpoints.add(endpoint);
  133. }
  134. }
  135. // Find the best presence
  136. Mode bestPresence = null;
  137. for (XmppEndpoint endpoint : bestEndpoints) {
  138. final Mode targetMode = endpoint.getMode() == null ? Mode.available : endpoint.getMode();
  139. if (bestPresence == null || bestPresence.compareTo(targetMode) > 0) {
  140. bestPresence = targetMode;
  141. }
  142. }
  143. return bestPresence;
  144. }
  145. /**
  146. * Updates this client with information from the roster.
  147. *
  148. * @param entry The roster entry to update this client with
  149. */
  150. public void setRosterEntry(final RosterEntry entry) {
  151. setRealname(entry.getName());
  152. }
  153. @Override
  154. public XmppParser getParser() {
  155. return (XmppParser) super.getParser();
  156. }
  157. }