 		 */
 		public function setPresence( show:String, status:String, priority:Number ):void
 		{
-			//var tempPresence:Presence = new Presence( null, null, Presence.AVAILABLE_TYPE, show, status, priority );
-			var tempPresence:Presence = new Presence( null, null, null, show, status, priority );
-			_connection.send( tempPresence );
-		}
-		
+			var presence:Presence = new Presence( null, null, null, show, status,
+													  priority );
+			_connection.send( presence );
+		}
+
 		/**
 		 *
 		 * @param	resultIQ
 		 */
-		public function fetchRoster_result( resultIQ:IQ ):void
-		{
-			// Clear out the old roster
-			removeAll();
-			try
-			{
-				disableAutoUpdate();
-				for each(var ext:RosterExtension in resultIQ.getAllExtensionsByNS( RosterExtension.NS ))
-				{
-					for each(var item:* in ext.getAllItems())
-					{
-						//var classInfo:XML = flash.utils.describeType(item);
-						if (!item is XMLStanza)
-						{
-							continue;
-						}
-						
-						var askType:String = item.askType != null ? item.askType.toLowerCase() : RosterExtension.ASK_TYPE_NONE;
-						addRosterItem( new UnescapedJID(item.jid), item.name, RosterExtension.SHOW_UNAVAILABLE,
-							"Offline", item.groupNames, item.subscription.toLowerCase(), askType);
-					}
-				}
-				enableAutoUpdate();
-				
-				// Fire Roster Loaded Event
-				var rosterEvent:RosterEvent = new RosterEvent(RosterEvent.ROSTER_LOADED, false, false);
-				dispatchEvent(rosterEvent);
-			}
-			catch (e:Error)
-			{
-				trace(e.getStackTrace());
-			}
-		}
-	
-		/**
-		 *
-		 * @param	resultIQ
-		 */
-		public function addContact_result( resultIQ:IQ ):void
-		{
-			// Contact was added, request subscription
-			requestSubscription( pendingSubscriptionRequestJID );
-			pendingSubscriptionRequestJID = null;
-		}
-		
-		/**
-		 *
-		 * @param	resultIQ
-		 */
 		public function unsubscribe_result( resultIQ:IQ ):void
 		{
 			// Does nothing for now
 		}
-			
+
+		/**
+		 * Updates the groups associated with an existing contact.
+		 *
+		 * @param	rosterItem The value object of the contact to update
+		 * @param	newGroups The new groups to associate the contact with
+		 */
+		public function updateContactGroups( rosterItem:RosterItemVO, newGroupNames:Array ):void
+		{
+			updateContact( rosterItem, rosterItem.displayName, newGroupNames );
+		}
+
+		/**
+		 * Updates the display name for an existing contact.
+		 *
+		 * @param	rosterItem The value object of the contact to update
+		 * @param	newName The new display name for this contact
+		 */
+		public function updateContactName( rosterItem:RosterItemVO, newName:String ):void
+		{
+			var groupNames:Array = [];
+			for each ( var group:RosterGroup in getContainingGroups( rosterItem ) )
+			{
+				groupNames.push( group.label );
+			}
+			updateContact( rosterItem, newName, groupNames );
+		}
+
+		private function addRosterItem( jid:UnescapedJID, displayName:String, show:String, status:String, groupNames:Array, type:String, askType:String = "none" ):Boolean
+		{
+			if ( !jid )
+			{
+				return false;
+			}
+
+			var rosterItem:RosterItemVO = RosterItemVO.get( jid, true );
+			if ( !contains( rosterItem ) )
+			{
+				addItem( rosterItem );
+			}
+			if ( displayName )
+			{
+				rosterItem.displayName = displayName;
+			}
+			rosterItem.subscribeType = type;
+			rosterItem.askType = askType;
+			rosterItem.status = status;
+			rosterItem.show = show;
+			setContactGroups( rosterItem, groupNames );
+
+			var event:RosterEvent = new RosterEvent( RosterEvent.USER_ADDED );
+			event.jid = jid;
+			event.data = rosterItem;
+			dispatchEvent( event );
+
+			return true;
+		}
+
 		/**
 		 *
 		 * @param	eventObj PresenceEvent, LoginEvent or RosterExtension

			{
				displayName = id.toString();
			}
				
			var callbackObj:Roster = null;
			var callbackMethod:String = null;
			var subscription:String = RosterExtension.SUBSCRIBE_TYPE_NONE;
			var askType:String = RosterExtension.ASK_TYPE_NONE;
			
			if ( requestSubscription == true )
			{
				callbackObj = this;

		{
			var tempPresence:Presence = new Presence( tojid.escaped, null, Presence.SUBSCRIBED_TYPE );
			_connection.send( tempPresence );

			// Request a return subscription
			if ( requestAfterGrant )
			{
				requestSubscription( tojid, true );
			}
		}

		/**
		 * 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
			}
		}

		/**
		 * 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 presence:Presence;
			if ( isResponse )
			{
				presence = new Presence( id.escaped, null, Presence.SUBSCRIBE_TYPE );
				_connection.send( presence );
				return;
			}
			// Only request for items in the roster
			if ( contains( RosterItemVO.get( id, false ) ) )
			{
				presence = new Presence( id.escaped, null, Presence.SUBSCRIBE_TYPE );
				_connection.send( presence );
			}
		}

		/**
		 * Sets your current presence status. Calling this method notifies others who
		 * are subscribed to your presence of a presence change. You should use this to
