1 /** 2 * $RCSfile$ 3 * $Revision$ 4 * $Date$ 5 * 6 * Copyright 2003-2007 Jive Software. 7 * 8 * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 package org.jivesoftware.smackx.packet; 22 23 import org.jivesoftware.smack.Roster; 24 import org.jivesoftware.smack.RosterEntry; 25 import org.jivesoftware.smack.RosterGroup; 26 import org.jivesoftware.smack.packet.PacketExtension; 27 import org.jivesoftware.smackx.RemoteRosterEntry; 28 29 import java.util.ArrayList; 30 import java.util.Collections; 31 import java.util.Iterator; 32 import java.util.List; 33 34 /** 35 * Represents XMPP Roster Item Exchange packets.<p> 36 * 37 * The 'jabber:x:roster' namespace (which is not to be confused with the 'jabber:iq:roster' 38 * namespace) is used to send roster items from one client to another. A roster item is sent by 39 * adding to the <message/> element an <x/> child scoped by the 'jabber:x:roster' namespace. This 40 * <x/> element may contain one or more <item/> children (one for each roster item to be sent).<p> 41 * 42 * Each <item/> element may possess the following attributes:<p> 43 * 44 * <jid/> -- The id of the contact being sent. This attribute is required.<br> 45 * <name/> -- A natural-language nickname for the contact. This attribute is optional.<p> 46 * 47 * Each <item/> element may also contain one or more <group/> children specifying the 48 * natural-language name of a user-specified group, for the purpose of categorizing this contact 49 * into one or more roster groups. 50 * 51 * @author Gaston Dombiak 52 */ 53 public class RosterExchange implements PacketExtension { 54 55 private List<RemoteRosterEntry> remoteRosterEntries = new ArrayList<RemoteRosterEntry>(); 56 57 /** 58 * Creates a new empty roster exchange package. 59 * 60 */ 61 public RosterExchange() { 62 super(); 63 } 64 65 /** 66 * Creates a new roster exchange package with the entries specified in roster. 67 * 68 * @param roster the roster to send to other XMPP entity. 69 */ 70 public RosterExchange(Roster roster) { 71 // Add all the roster entries to the new RosterExchange 72 for (RosterEntry rosterEntry : roster.getEntries()) { 73 this.addRosterEntry(rosterEntry); 74 } 75 } 76 77 /** 78 * Adds a roster entry to the packet. 79 * 80 * @param rosterEntry a roster entry to add. 81 */ 82 public void addRosterEntry(RosterEntry rosterEntry) { 83 // Obtain a String[] from the roster entry groups name 84 List<String> groupNamesList = new ArrayList<String>(); 85 String[] groupNames; 86 for (RosterGroup group : rosterEntry.getGroups()) { 87 groupNamesList.add(group.getName()); 88 } 89 groupNames = groupNamesList.toArray(new String[groupNamesList.size()]); 90 91 // Create a new Entry based on the rosterEntry and add it to the packet 92 RemoteRosterEntry remoteRosterEntry = new RemoteRosterEntry(rosterEntry.getUser(), 93 rosterEntry.getName(), groupNames); 94 95 addRosterEntry(remoteRosterEntry); 96 } 97 98 /** 99 * Adds a remote roster entry to the packet. 100 * 101 * @param remoteRosterEntry a remote roster entry to add. 102 */ 103 public void addRosterEntry(RemoteRosterEntry remoteRosterEntry) { 104 synchronized (remoteRosterEntries) { 105 remoteRosterEntries.add(remoteRosterEntry); 106 } 107 } 108 109 /** 110 * Returns the XML element name of the extension sub-packet root element. 111 * Always returns "x" 112 * 113 * @return the XML element name of the packet extension. 114 */ 115 public String getElementName() { 116 return "x"; 117 } 118 119 /** 120 * Returns the XML namespace of the extension sub-packet root element. 121 * According the specification the namespace is always "jabber:x:roster" 122 * (which is not to be confused with the 'jabber:iq:roster' namespace 123 * 124 * @return the XML namespace of the packet extension. 125 */ 126 public String getNamespace() { 127 return "jabber:x:roster"; 128 } 129 130 /** 131 * Returns an Iterator for the roster entries in the packet. 132 * 133 * @return an Iterator for the roster entries in the packet. 134 */ 135 public Iterator<RemoteRosterEntry> getRosterEntries() { 136 synchronized (remoteRosterEntries) { 137 List<RemoteRosterEntry> entries = Collections.unmodifiableList(new ArrayList<RemoteRosterEntry>(remoteRosterEntries)); 138 return entries.iterator(); 139 } 140 } 141 142 /** 143 * Returns a count of the entries in the roster exchange. 144 * 145 * @return the number of entries in the roster exchange. 146 */ 147 public int getEntryCount() { 148 return remoteRosterEntries.size(); 149 } 150 151 /** 152 * Returns the XML representation of a Roster Item Exchange according the specification. 153 * 154 * Usually the XML representation will be inside of a Message XML representation like 155 * in the following example: 156 * <pre> 157 * <message id="MlIpV-4" to="gato1 (at) gato.home" from="gato3 (at) gato.home/Smack"> 158 * <subject>Any subject you want</subject> 159 * <body>This message contains roster items.</body> 160 * <x xmlns="jabber:x:roster"> 161 * <item jid="gato1 (at) gato.home"/> 162 * <item jid="gato2 (at) gato.home"/> 163 * </x> 164 * </message> 165 * </pre> 166 * 167 */ 168 public String toXML() { 169 StringBuilder buf = new StringBuilder(); 170 buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append( 171 "\">"); 172 // Loop through all roster entries and append them to the string buffer 173 for (Iterator<RemoteRosterEntry> i = getRosterEntries(); i.hasNext();) { 174 RemoteRosterEntry remoteRosterEntry = i.next(); 175 buf.append(remoteRosterEntry.toXML()); 176 } 177 buf.append("</").append(getElementName()).append(">"); 178 return buf.toString(); 179 } 180 181 } 182