 				subscription = RosterExtension.SUBSCRIBE_TYPE_TO;
 				askType = RosterExtension.ASK_TYPE_SUBSCRIBE
 			}
-				
-			var tempIQ:IQ = new IQ (null, IQ.SET_TYPE, XMPPStanza.generateID("add_user_"), callbackMethod, callbackObj );
+
+			var tempIQ:IQ = new IQ( null, IQ.SET_TYPE, XMPPStanza.generateID( "add_user_" ),
+									callbackMethod, callbackObj );
 			var ext:RosterExtension = new RosterExtension( tempIQ.getNode() );
-			ext.addItem( id.escaped, null, displayName, groupName ? [groupName] : null );
+			ext.addItem( id.escaped, null, displayName, groupName ? [ groupName ] :
+						 null );
 			tempIQ.addExtension( ext );
 			_connection.send( tempIQ );
-	
-			
+
+
 			addRosterItem( id, displayName, RosterExtension.SHOW_PENDING, RosterExtension.SHOW_PENDING,
-				[groupName], subscription, askType );
-		}
-		
-		/**
-		 * Requests subscription authorization with a user or service. In the XMPP-world, you cannot receive
-		 * notifications on changes to a contact's presence until that contact has authorized you to subscribe
-		 * to his/her/its presence.
-		 *
-		 * @param	id The JID of the user or service that you wish to subscribe to
-		 * @param	isResponse
-		 * @see	#subscriptionDenial
-		 */
-		public function requestSubscription( id:UnescapedJID, isResponse:Boolean = false):void
-		{
-			// Roster length is 0 if it a response to a user request. we must handle this event.
-			var tempPresence:Presence;
-			if (isResponse)
-			{
-				tempPresence = new Presence( id.escaped, null, Presence.SUBSCRIBE_TYPE );
-				_connection.send( tempPresence );
-				return;
-			}
-			// Only request for items in the roster
-			if (contains(RosterItemVO.get(id, false)))
-			{
-				tempPresence = new Presence( id.escaped, null, Presence.SUBSCRIBE_TYPE );
-				_connection.send( tempPresence );
-			}
-		}
-		
-		/**
-		 * Removes a contact from the roster and revokes all presence subscriptions for that contact.
-		 * This method will only attempt action if the contact you are trying to remove is currently on the
-		 * roster in the first place.
-		 *
-		 * @param	rosterItem The value object which is to be removed
-		 */
-		public function removeContact( rosterItem:RosterItemVO ):void
-		{
-			if (contains(rosterItem))
-			{
-				var tempIQ:IQ = new IQ( null, IQ.SET_TYPE, XMPPStanza.generateID("remove_user_"), "unsubscribe_result", this );
-				var ext:RosterExtension = new RosterExtension( tempIQ.getNode() );
-				ext.addItem( new EscapedJID(rosterItem.jid.bareJID), RosterExtension.SUBSCRIBE_TYPE_REMOVE );
-				tempIQ.addExtension( ext );
-				_connection.send( tempIQ );
-				
-				//the roster item is not actually removed from the roster
-				//until confirmation comes back from the XMPP server
-			}
-		}
-		
+						   [ groupName ], subscription, askType );
+		}
+
+		/**
+		 *
+		 * @param	resultIQ
+		 */
+		public function addContact_result( resultIQ:IQ ):void
+		{
+			// Contact was added, request subscription
+			requestSubscription( pendingSubscriptionRequestJID );
+			pendingSubscriptionRequestJID = null;
+		}
+
+		/**
+		 * Revokes an existing presence subscription or denies a subscription request. If a user
+		 * has sent you a subscription request you can use this method to deny that request. Otherwise,
+		 * if a user already has a granted presence subscription, you can use this method to revoke that
+		 * subscription.
+		 *
+		 * @param	tojid The JID of the user or service that you are denying subscription
+		 */
+		public function denySubscription( tojid:UnescapedJID ):void
+		{
+			var tempPresence:Presence = new Presence( tojid.escaped, null, Presence.UNSUBSCRIBED_TYPE );
+			_connection.send( tempPresence );
+		}
+
 		/**
 		 * Fetches the roster data from the server. Once the data has been fetched, the Roster's data
 		 * provider is populated appropriately. If the Roster-XMPPConnection class dependency has been

	 */
	public class Roster extends ArrayCollection
	{
		private var _connection:XMPPConnection;
		
		//FIXME: does not support multiple pending requests
		private var pendingSubscriptionRequestJID:UnescapedJID;
		
		/**
		 * Store presences of the people in users roster.
		 */
		private var _presenceMap:Dictionary;
		
		/**
		 * Store groups as RosterGroup.
		 */
		private var _groups:Dictionary;
		
		private static const staticConstructorDependencies:Array = [
			ExtensionClassRegistry,
			RosterExtension
		]
		
		private static var rosterStaticConstructed:Boolean = RosterStaticConstructor();
		
		/**
		 *
		 * @param	aConnection A reference to an XMPPConnection class instance
		 */
		public function Roster( aConnection:XMPPConnection = null )
		{
			_presenceMap = new Dictionary();
			_groups = new Dictionary();
			
			if (aConnection != null)
			{
				connection = aConnection;
			}
		}
		
		/**
		 *
		 * @return

				item.status = presence.status;
				item.show = presence.show;
				item.priority = presence.priority;
				if ( !presence.type )
				{
					item.online = true;
				}
				else if ( presence.type == Presence.UNAVAILABLE_TYPE )
				{
					item.online = false;
				}

				var event:RosterEvent = new RosterEvent( RosterEvent.USER_PRESENCE_UPDATED );
				event.jid = item.jid;
				event.data = item;
				dispatchEvent( event );

				_presenceMap[ item.jid.toString() ] = presence;
			}
			catch ( e:Error )
			{
				trace( e.getStackTrace() );
			}
		}

		private function updateRosterItemSubscription( item:RosterItemVO, type:String, name:String, newGroupNames:Array ):void
		{
			item.subscribeType = type;

			setContactGroups( item, newGroupNames );

			if ( name )
			{
				item.displayName = name;
			}

			var event:RosterEvent = new RosterEvent( RosterEvent.USER_SUBSCRIPTION_UPDATED );
			event.jid = item.jid;
			event.data = item;
			dispatchEvent( event );
		}

		/**
		 * The instance of the XMPPConnection class to use for the roster to use for
		 * sending and receiving data.
