You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@labs.apache.org by be...@apache.org on 2008/10/14 21:50:53 UTC

svn commit: r704646 - in /labs/vysper/src: main/java/org/apache/vysper/xmpp/modules/core/im/handler/ main/java/org/apache/vysper/xmpp/modules/roster/ main/java/org/apache/vysper/xmpp/modules/roster/persistence/ test/java/org/apache/vysper/xmpp/modules/...

Author: berndf
Date: Tue Oct 14 12:50:53 2008
New Revision: 704646

URL: http://svn.apache.org/viewvc?rev=704646&view=rev
Log:
[vysper] more on the subscription state machine. adopt RosterManager API to actual needs. more improvments to presence sub handling

Modified:
    labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/core/im/handler/PresenceSubscriptionHandler.java
    labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/RosterSubscriptionMutator.java
    labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/persistence/MemoryRosterManager.java
    labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/persistence/RosterManager.java
    labs/vysper/src/test/java/org/apache/vysper/xmpp/modules/roster/RosterSubscriptionMutatorTestCase.java

Modified: labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/core/im/handler/PresenceSubscriptionHandler.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/core/im/handler/PresenceSubscriptionHandler.java?rev=704646&r1=704645&r2=704646&view=diff
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/core/im/handler/PresenceSubscriptionHandler.java (original)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/core/im/handler/PresenceSubscriptionHandler.java Tue Oct 14 12:50:53 2008
@@ -23,11 +23,10 @@
 import org.apache.vysper.xmpp.delivery.DeliveryException;
 import org.apache.vysper.xmpp.delivery.StanzaRelay;
 import org.apache.vysper.xmpp.delivery.failure.IgnoreFailureStrategy;
-import org.apache.vysper.xmpp.modules.roster.AskSubscriptionType;
-import org.apache.vysper.xmpp.modules.roster.RosterException;
-import org.apache.vysper.xmpp.modules.roster.RosterItem;
-import org.apache.vysper.xmpp.modules.roster.RosterStanzaUtils;
-import org.apache.vysper.xmpp.modules.roster.SubscriptionType;
+import org.apache.vysper.xmpp.modules.roster.*;
+import static org.apache.vysper.xmpp.modules.roster.RosterSubscriptionMutator.Result.*;
+import static org.apache.vysper.xmpp.modules.roster.AskSubscriptionType.*;
+import static org.apache.vysper.xmpp.modules.roster.SubscriptionType.*;
 import org.apache.vysper.xmpp.modules.roster.persistence.RosterManager;
 import org.apache.vysper.xmpp.protocol.NamespaceURIs;
 import org.apache.vysper.xmpp.resourcebinding.ResourceRegistry;
@@ -83,7 +82,7 @@
                 case SUBSCRIBE:
                     // RFC3921bis-04#3.1.2
                     // user requests subsription to contact
-                    handleOutboundSubscriptionRequest(stampedStanza, sessionContext, registry);
+                    handleOutboundSubscriptionRequest(stampedStanza, sessionContext, registry, rosterManager);
                     break;
                 
                 case SUBSCRIBED:
@@ -95,13 +94,13 @@
                 case UNSUBSCRIBE:
                     // RFC3921bis-04#3.3.2
                     // user removes subscription from contact
-                    handleOutboundUnsubscription(stampedStanza, sessionContext, registry);
+                    handleOutboundUnsubscription(stampedStanza, sessionContext, registry, rosterManager);
                     break;
                 
                 case UNSUBSCRIBED:
                     // RFC3921bis-04#3.2.2
                     // user approves unsubscription of contact 
-                    handleOutboundSubscriptionCancellation(stampedStanza, sessionContext, registry);
+                    handleOutboundSubscriptionCancellation(stampedStanza, sessionContext, registry, rosterManager);
                     break;
                 
                 default:
@@ -120,21 +119,21 @@
                 case SUBSCRIBED:
                     // RFC3921bis-04#3.1.6
                     // contact approves user's subsription request
-                    return handleInboundSubscriptionApproval(presenceStanza, sessionContext, registry);
+                    return handleInboundSubscriptionApproval(presenceStanza, sessionContext, registry, rosterManager);
 
                 case UNSUBSCRIBE:
                     // RFC3921bis-04#3.3.3
-                    // contact unsubscribes 
-                    handleInboundUnsubscription(presenceStanza, sessionContext, registry);
+                    // contact unsubscribes
+                    handleInboundUnsubscription(presenceStanza, sessionContext, registry, rosterManager);
 
                 case UNSUBSCRIBED:
                     // RFC3921bis-04#3.2.3
                     // contact denies subsription
-                    handleInboundSubscriptionCancellation(presenceStanza, sessionContext, registry);
+                    handleInboundSubscriptionCancellation(presenceStanza, sessionContext, registry, rosterManager);
 
                 default:
                     throw new RuntimeException("unhandled case " + type.value());
-                    
+
             }
         }
 
@@ -171,7 +170,7 @@
     
  */
     @SpecCompliant(spec = "RFC3921bis-04", section = "3.3.3")
-	private void handleInboundUnsubscription(PresenceStanza stanza, SessionContext sessionContext, ResourceRegistry registry) {
+	protected void handleInboundUnsubscription(PresenceStanza stanza, SessionContext sessionContext, ResourceRegistry registry, RosterManager rosterManager) {
 		Entity contact = stanza.getFrom();
 		Entity user = stanza.getTo();
 
@@ -237,8 +236,8 @@
 
  */
 	@SpecCompliant(spec = "RFC3921bis-04", section = "3.3.2")
-	private void handleOutboundUnsubscription(PresenceStanza stanza,
-                                           SessionContext sessionContext, ResourceRegistry registry) {
+	protected void handleOutboundUnsubscription(PresenceStanza stanza,
+                                             SessionContext sessionContext, ResourceRegistry registry, RosterManager rosterManager) {
 		Entity user = stanza.getFrom();
 		Entity contact = stanza.getTo();
 
@@ -288,8 +287,8 @@
 
  */
     @SpecCompliant(spec = "RFC3921bis-04", section = "3.2.3")
-	private void handleInboundSubscriptionCancellation(PresenceStanza stanza,
-                                                    SessionContext sessionContext, ResourceRegistry registry) {
+	protected void handleInboundSubscriptionCancellation(PresenceStanza stanza,
+                                                      SessionContext sessionContext, ResourceRegistry registry, RosterManager rosterManager) {
 
         // TODO: check if client actually requested subscription
 		// TODO: update roster for user
@@ -358,8 +357,8 @@
     
 */
     @SpecCompliant(spec = "RFC3921bis-04", section = "3.2.2")
-	private void handleOutboundSubscriptionCancellation(PresenceStanza stanza,
-                                                     SessionContext sessionContext, ResourceRegistry registry) {
+	protected void handleOutboundSubscriptionCancellation(PresenceStanza stanza,
+                                                       SessionContext sessionContext, ResourceRegistry registry, RosterManager rosterManager) {
 		Entity user = stanza.getFrom();
 		Entity contact = stanza.getTo();
 
@@ -435,7 +434,7 @@
     
      */
     @SpecCompliant(spec = "RFC3921bis-04", section = "3.1.5")
-	private void handleOutboundSubscriptionApproval(PresenceStanza stanza,
+	protected void handleOutboundSubscriptionApproval(PresenceStanza stanza,
                                                  SessionContext sessionContext, ResourceRegistry registry, RosterManager rosterManager) 
     {
 		Entity user = stanza.getFrom();
@@ -444,28 +443,21 @@
         Entity userBareJid = user.getBareJID();
         Entity contactBareJid = contact.getBareJID();
 
-        // record TO (= contact is subscribed to user) relationship
-        // TODO check if BOTH is needed
-        SubscriptionType newSubscriptionType = SubscriptionType.TO;
-        RosterItem newItem = new RosterItem(userBareJid, newSubscriptionType);
+        RosterItem rosterItem = null;
         try {
-            rosterManager.addContact(contactBareJid, newItem);
+            rosterItem = getExistingOrNewRosterItem(rosterManager, userBareJid, contactBareJid);
         } catch (RosterException e) {
-            // TODO internal server error
-            // contact could not be added
+            e.printStackTrace();
+            throw new RuntimeException(e);
         }
         
-        // record FROM (= contact receives presence from user) relationship
-        // TODO check if BOTH is needed
-        newSubscriptionType = SubscriptionType.FROM;
-        newItem = new RosterItem(contactBareJid, newSubscriptionType);
-        try {
-            rosterManager.addContact(userBareJid, newItem);
-        } catch (RosterException e) {
-            // TODO internal server error
-            // contact could not be added
+        RosterSubscriptionMutator.Result result = RosterSubscriptionMutator.getInstance().add(rosterItem, TO);
+
+        if (result != OK) {
+            // TODO
+            return;
         }
-        
+
         relayStanza(contact, stanza, sessionContext);
 
         // send roster push to all of the user's interested resources
@@ -473,10 +465,7 @@
 
 		for (String resource : resources) {
 			Entity userResource = new EntityImpl(user, resource);
-			Stanza push = buildRosterPushStanza(userResource,
-					sessionContext.nextSequenceValue(), contactBareJid,
-                    newSubscriptionType, null);
-
+			Stanza push = buildRosterPushStanza(userResource, sessionContext.nextSequenceValue(), rosterItem);
 			relayStanza(userResource, push, sessionContext);
 		}
 
@@ -485,84 +474,94 @@
 		resources = registry.getAvailableResources(user);
 		for (String resource : resources) {
 			Entity userResource = new EntityImpl(user, resource);
+            // TODO check: send real presence, or initial pres?
 			Stanza presence = buildPresenceStanza(userResource, contactBareJid, null, null);
 
 			relayStanza(contact, presence, sessionContext);
 		}
 	}
 
-/*
-3.1.6.  Server Processing of Inbound Subscription Approval
-
-   When the user's server receives the subscription approval, it MUST
-   first check if the contact is in the user's roster with a
-   subscription='none' or subscription='from' and the 'ask' flag set to
-   "subscribe" (i.e., a subscription states of "None + Pending Out" or
-   "From + Pending Out"; see Appendix A).  If the contact is not in the
-   user's roster with either of those states, the user's server MUST
-   silently ignore the presence stanza of type "subscribed" (i.e., it
-   MUST NOT route it to the user, modify the user's roster, or generate
-   a roster push to the user's interested resources).
-
-   If the foregoing check is successful, the user's server MUST initiate
-   a roster push to all of the user's interested resources, containing
-   an updated roster item for the contact with the 'subscription'
-   attribute set to a value of "to".
-
-   US: <iq to='romeo@example.net/foo'
-           type='set'
-           id='b89c5r7ib576'>
-         <query xmlns='jabber:iq:roster'>
-           <item jid='juliet@example.com'
-                 subscription='to'/>
-         </query>
-       </iq>
-
-   US: <iq to='romeo@example.net/bar'
-           type='set'
-           id='b89c5r7ib577'>
-         <query xmlns='jabber:iq:roster'>
-           <item jid='juliet@example.com'
-                 subscription='to'/>
-           </item>
-         </query>
-       </iq>
-
-   From the perspective of the user, there now exists a subscription to
-   the contact's presence.
-
-   The user's server MUST also deliver the available presence stanza
-   received from each of the contact's available resources to each of
-   the user's available resources.
-
-   [ ... to resource1 ... ]
-
-   US: <presence from='juliet@example.com/balcony'
-                 to='romeo@example.net'/>
-
-   [ ... to resource2 ... ]
+    private RosterItem getExistingOrNewRosterItem(RosterManager rosterManager, Entity userJid, Entity contactJid) throws RosterException {
+        RosterItem rosterItem = rosterManager.getContact(userJid, contactJid);
+        if (rosterItem == null) {
+            rosterItem = new RosterItem(contactJid, NONE);
+            rosterManager.addContact(userJid, rosterItem);
+        }
+        return rosterItem;
+    }
 
-   US: <presence from='juliet@example.com/balcony'
-                 to='romeo@example.net'/>
+    /*
+    3.1.6.  Server Processing of Inbound Subscription Approval
 
-   [ ... to resource1 ... ]
+       When the user's server receives the subscription approval, it MUST
+       first check if the contact is in the user's roster with a
+       subscription='none' or subscription='from' and the 'ask' flag set to
+       "subscribe" (i.e., a subscription states of "None + Pending Out" or
+       "From + Pending Out"; see Appendix A).  If the contact is not in the
+       user's roster with either of those states, the user's server MUST
+       silently ignore the presence stanza of type "subscribed" (i.e., it
+       MUST NOT route it to the user, modify the user's roster, or generate
+       a roster push to the user's interested resources).
+
+       If the foregoing check is successful, the user's server MUST initiate
+       a roster push to all of the user's interested resources, containing
+       an updated roster item for the contact with the 'subscription'
+       attribute set to a value of "to".
+
+       US: <iq to='romeo@example.net/foo'
+               type='set'
+               id='b89c5r7ib576'>
+             <query xmlns='jabber:iq:roster'>
+               <item jid='juliet@example.com'
+                     subscription='to'/>
+             </query>
+           </iq>
+
+       US: <iq to='romeo@example.net/bar'
+               type='set'
+               id='b89c5r7ib577'>
+             <query xmlns='jabber:iq:roster'>
+               <item jid='juliet@example.com'
+                     subscription='to'/>
+               </item>
+             </query>
+           </iq>
+
+       From the perspective of the user, there now exists a subscription to
+       the contact's presence.
+
+       The user's server MUST also deliver the available presence stanza
+       received from each of the contact's available resources to each of
+       the user's available resources.
+
+       [ ... to resource1 ... ]
+
+       US: <presence from='juliet@example.com/balcony'
+                     to='romeo@example.net'/>
+
+       [ ... to resource2 ... ]
+
+       US: <presence from='juliet@example.com/balcony'
+                     to='romeo@example.net'/>
+
+       [ ... to resource1 ... ]
+
+       US: <presence from='juliet@example.com/chamber'
+                     to='romeo@example.net'/>
 
-   US: <presence from='juliet@example.com/chamber'
-                 to='romeo@example.net'/>
+       [ ... to resource2 ... ]
 
-   [ ... to resource2 ... ]
+       US: <presence from='juliet@example.com/chamber'
+                     to='romeo@example.net'/>
 
-   US: <presence from='juliet@example.com/chamber'
-                 to='romeo@example.net'/>
-    
-*/
+    */
     /**
      * TODO this handling method should be optimized to be processed only once for every session
      *      DeliveringInboundStanzaRelay call this for every resource separately 
      */
     @SpecCompliant(spec = "RFC3921bis-04", section = "3.1.6")
-	private Stanza handleInboundSubscriptionApproval(PresenceStanza stanza,
-                                                  SessionContext sessionContext, ResourceRegistry registry) {
+	protected Stanza handleInboundSubscriptionApproval(PresenceStanza stanza,
+                                                    SessionContext sessionContext, ResourceRegistry registry, RosterManager rosterManager) {
 
 		// TODO: check if contact is in users roster with
 		// subscription="from||none" && ask="subscribe"
@@ -579,7 +578,7 @@
 			for (String resource : resources) {
 				Entity userResource = new EntityImpl(user, resource);
 				Stanza push = buildRosterPushStanza(userResource, sessionContext.nextSequenceValue(), 
-                        contact.getBareJID(), SubscriptionType.TO, null /*TODO ask? */);
+                        contact.getBareJID(), TO, null /*TODO ask? */);
                 sessionContext.getResponseWriter().write(push);
 			}
             
@@ -659,7 +658,7 @@
     
      */
     @SpecCompliant(spec = "RFC3920bis-04", section = "3.1.3")
-	private Stanza handleInboundSubscriptionRequest(PresenceStanza stanza,
+	protected Stanza handleInboundSubscriptionRequest(PresenceStanza stanza,
                                                  SessionContext sessionContext, ResourceRegistry registry, RosterManager rosterManager) {
         ServerRuntimeContext serverRuntimeContext = sessionContext.getServerRuntimeContext();
 
@@ -668,15 +667,18 @@
         
         Entity userBareJid = user.getBareJID();
 
-        RosterItem item = null;
+        RosterItem rosterItem;
         try {
-            item = rosterManager.retrieve(userBareJid).getEntry(contact);
+            rosterItem = getExistingOrNewRosterItem(rosterManager, userBareJid, contact);
         } catch (RosterException e) {
-            // item could not be retrieved
+            e.printStackTrace();
+            throw new RuntimeException(e);
         }
-    
+
+        RosterSubscriptionMutator.Result result = RosterSubscriptionMutator.getInstance().add(rosterItem, ASK_SUBSCRIBED);
+
         // check whether user already has a subscription to contact
-		if (item != null && item.hasFrom() ) {
+		if (result == ALREADY_SET) {
             Entity receiver = contact.getBareJID();
             PresenceStanza alreadySubscribedResponse = buildPresenceStanza(userBareJid, receiver, SUBSCRIBED, stanza);
             relayStanza(receiver, alreadySubscribedResponse, sessionContext);
@@ -690,17 +692,6 @@
         // write inbound stanza to the user 
         sessionContext.getResponseWriter().write(stanza);
 
-        // send roster push to all of the user's interested resources
-        // TODO do this only once, since inbound is multiplexed on DeliveringInboundStanzaRelay level already 
-        StanzaRelay stanzaRelay = serverRuntimeContext.getStanzaRelay();
-        List<String> resources = registry.getInterestedResources(user);
-        for (String resource : resources) {
-            Entity userResource = new EntityImpl(user, resource);
-            Stanza push = buildRosterPushStanza(userResource,
-                    sessionContext.nextSequenceValue(), contact.getBareJID(),
-                    SubscriptionType.TO, AskSubscriptionType.ASK_SUBSCRIBED);
-            sessionContext.getResponseWriter().write(push);
-        }
 		return null;
 	}
 
@@ -771,8 +762,8 @@
 */
 
 	@SpecCompliant(spec = "RFC3920bis-04", section = "3.1.2")
-	private void handleOutboundSubscriptionRequest(PresenceStanza stanza,
-                                                SessionContext sessionContext, ResourceRegistry registry) {
+	protected void handleOutboundSubscriptionRequest(PresenceStanza stanza,
+                                                  SessionContext sessionContext, ResourceRegistry registry, RosterManager rosterManager) {
 		ServerRuntimeContext serverRuntimeContext = sessionContext.getServerRuntimeContext();
 		StanzaRelay stanzaRelay = serverRuntimeContext.getStanzaRelay();
 
@@ -786,15 +777,34 @@
 		Entity user = stanza.getFrom();
 		Entity contact = stanza.getTo();
 
-		// send roster push to all of the user's interested resources
+        // TODO schedule a observer which can re-send the request
+
+        Roster roster = null;
+        try {
+            roster = rosterManager.retrieve(user);
+        } catch (RosterException e) {
+            // TODO send internal server error or something like that
+            e.printStackTrace();
+            return;
+        }
+
+        RosterItem contactItem = roster.getEntry(contact);
+        if (contactItem == null) {
+            contactItem = new RosterItem(contact, NONE);
+        }
+
+        RosterSubscriptionMutator.Result result = RosterSubscriptionMutator.getInstance().add(contactItem, ASK_SUBSCRIBE);
+        if (result != OK) {
+            
+        }
+
+        // send roster push to all of the user's interested resources
 		List<String> resources = registry.getInterestedResources(user);
 		for (String resource : resources) {
 			Entity userResource = new EntityImpl(user, resource);
-			Stanza push = buildRosterPushStanza(userResource,
-					sessionContext.nextSequenceValue(), contact.getBareJID(),
-                    SubscriptionType.TO, AskSubscriptionType.ASK_SUBSCRIBE);
-			try {
-				stanzaRelay.relay(userResource, push, new IgnoreFailureStrategy());
+			Stanza push = buildRosterPushStanza(userResource, sessionContext.nextSequenceValue(), contactItem);
+            try {
+                stanzaRelay.relay(userResource, push, new IgnoreFailureStrategy());
 			} catch (DeliveryException e) {
 				e.printStackTrace();
 			}
@@ -809,22 +819,28 @@
 
 	private Stanza buildRosterPushStanza(Entity to, String id,
 			Entity bareJidOfRosterItem, SubscriptionType subscription, AskSubscriptionType ask) {
-        if (subscription == null) subscription = SubscriptionType.NONE;
-        if (ask == null) ask = AskSubscriptionType.NOT_SET;
-        
+        if (subscription == null) subscription = NONE;
+        if (ask == null) ask = NOT_SET;
+
+        RosterItem rosterItem = new RosterItem(bareJidOfRosterItem.getBareJID(), subscription, ask);
+
+        return buildRosterPushStanza(to, id, rosterItem);
+	}
+
+    private Stanza buildRosterPushStanza(Entity to, String id, RosterItem rosterItem) {
         StanzaBuilder builder = new StanzaBuilder("iq");
-		builder.addAttribute("to", to.getFullQualifiedName());
-		builder.addAttribute("type", "set");
-		builder.addAttribute("id", id);
-		builder.startInnerElement("query");
+        builder.addAttribute("to", to.getFullQualifiedName());
+        builder.addAttribute("type", "set");
+        builder.addAttribute("id", id);
+        builder.startInnerElement("query");
             builder.addNamespaceAttribute(NamespaceURIs.JABBER_IQ_ROSTER);
-            RosterStanzaUtils.createRosterItem(builder, new RosterItem(bareJidOfRosterItem.getBareJID(), subscription, ask));
-		builder.endInnerElement();
+            RosterStanzaUtils.createRosterItem(builder, rosterItem);
+        builder.endInnerElement();
 
-		return builder.getFinalStanza();
-	}
+        return builder.getFinalStanza();
+    }
 
-	private void relayStanza(Entity receiver, Stanza stanza, SessionContext sessionContext) {
+    private void relayStanza(Entity receiver, Stanza stanza, SessionContext sessionContext) {
 		try {
 			sessionContext.getServerRuntimeContext().getStanzaRelay().relay(receiver, stanza, new IgnoreFailureStrategy());
 		} catch (DeliveryException e) {

Modified: labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/RosterSubscriptionMutator.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/RosterSubscriptionMutator.java?rev=704646&r1=704645&r2=704646&view=diff
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/RosterSubscriptionMutator.java (original)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/RosterSubscriptionMutator.java Tue Oct 14 12:50:53 2008
@@ -16,25 +16,36 @@
  ***********************************************************************/
 package org.apache.vysper.xmpp.modules.roster;
 
-import static org.apache.vysper.xmpp.modules.roster.RosterSubscriptionMutator.RosterSubscriptionMutatorResult.*;
+import static org.apache.vysper.xmpp.modules.roster.RosterSubscriptionMutator.Result.*;
 import static org.apache.vysper.xmpp.modules.roster.SubscriptionType.*;
 import static org.apache.vysper.xmpp.modules.roster.AskSubscriptionType.*;
 
 /**
+ * changes roster item subscription and ask states according to the protocol's spec
  */
 public class RosterSubscriptionMutator {
 
-    enum RosterSubscriptionMutatorResult {
+    private static RosterSubscriptionMutator SINGLETON = new RosterSubscriptionMutator();
+
+    public static RosterSubscriptionMutator getInstance() {
+        return SINGLETON;
+    }
+
+    public enum Result {
         OK,
         ILLEGAL_ARGUMENT,
         ALREADY_SET,
         FAILED
     }
 
+    protected RosterSubscriptionMutator() {
+        ; // empty
+    }
+
     /**
      * adds a subscription request to the roster item
      */
-    public RosterSubscriptionMutatorResult add(RosterItem item, AskSubscriptionType addAskSubscriptionType) {
+    public Result add(RosterItem item, AskSubscriptionType addAskSubscriptionType) {
         synchronized (item) {
             return addWorker(item, addAskSubscriptionType);
         }
@@ -43,7 +54,7 @@
     /**
      * adds a subscription to the roster item
      */
-    public RosterSubscriptionMutatorResult add(RosterItem item, SubscriptionType addSubscriptionType) {
+    public Result add(RosterItem item, SubscriptionType addSubscriptionType) {
         synchronized (item) {
             return addWorker(item, addSubscriptionType);
         }
@@ -52,18 +63,18 @@
     /**
      * removes a subscription from the roster item
      */
-    public RosterSubscriptionMutatorResult remove(RosterItem item, SubscriptionType removeSubscriptionType) {
+    public Result remove(RosterItem item, SubscriptionType removeSubscriptionType) {
         synchronized (item) {
             return removeWorker(item, removeSubscriptionType);
         }
     }
 
-    protected RosterSubscriptionMutatorResult addWorker(RosterItem item, SubscriptionType addSubscriptionType) {
+    protected Result addWorker(RosterItem item, SubscriptionType addSubscriptionType) {
         switch (addSubscriptionType) {
             case NONE:
             case BOTH:
             case REMOVE:
-                return RosterSubscriptionMutatorResult.ILLEGAL_ARGUMENT;
+                return Result.ILLEGAL_ARGUMENT;
             case FROM:
                 return addFrom(item);
             case TO:
@@ -73,10 +84,10 @@
         }
     }
 
-    protected RosterSubscriptionMutatorResult addWorker(RosterItem item, AskSubscriptionType addAskSubscriptionType) {
+    protected Result addWorker(RosterItem item, AskSubscriptionType addAskSubscriptionType) {
         switch (addAskSubscriptionType) {
             case NOT_SET:
-                return RosterSubscriptionMutatorResult.ILLEGAL_ARGUMENT;
+                return Result.ILLEGAL_ARGUMENT;
             case ASK_SUBSCRIBE:
                 return addAskSubscribe(item);
             case ASK_SUBSCRIBED:
@@ -86,58 +97,58 @@
         }
     }
 
-    protected RosterSubscriptionMutatorResult addAskSubscribe(RosterItem item) {
+    protected Result addAskSubscribe(RosterItem item) {
         SubscriptionType type = item.getSubscriptionType();
         AskSubscriptionType typeAsk = item.getAskSubscriptionType();
         if (type.includesTo()) return ALREADY_SET;
-        if (typeAsk == ASK_SUBSCRIBE) return ALREADY_SET; 
+        if (typeAsk == ASK_SUBSCRIBE) return OK;
         // IGNORE this, overwrite! if (typeAsk == ASK_SUBSCRIBED) return ALREADY_SET; 
         item.setAskSubscriptionType(ASK_SUBSCRIBE);
         return OK;
     }
 
-    protected RosterSubscriptionMutatorResult addAskSubscribed(RosterItem item) {
+    protected Result addAskSubscribed(RosterItem item) {
         SubscriptionType type = item.getSubscriptionType();
         AskSubscriptionType typeAsk = item.getAskSubscriptionType();
         if (type.includesFrom()) return ALREADY_SET;
         if (typeAsk == ASK_SUBSCRIBE) return FAILED; // TODO think about return value 
-        if (typeAsk == ASK_SUBSCRIBED) return ALREADY_SET; 
+        if (typeAsk == ASK_SUBSCRIBED) return OK;
         item.setAskSubscriptionType(ASK_SUBSCRIBED);
         return OK;
     }
 
-    protected RosterSubscriptionMutatorResult addTo(RosterItem item) {
+    protected Result addTo(RosterItem item) {
         SubscriptionType type = item.getSubscriptionType();
         if (type.includesTo()) return ALREADY_SET;
         if (type == NONE) {
             type = TO;
         } else if (type == FROM) {
             type = BOTH;
-        }             
+        }
         item.setSubscriptionType(type);
         if (item.getAskSubscriptionType() == ASK_SUBSCRIBE) item.setAskSubscriptionType(NOT_SET);
         return OK;
     }
 
-    protected RosterSubscriptionMutatorResult addFrom(RosterItem item) {
+    protected Result addFrom(RosterItem item) {
         SubscriptionType type = item.getSubscriptionType();
         if (type.includesFrom()) return ALREADY_SET;
         if (type == NONE) {
             type = FROM;
-        } else if (type == FROM) {
+        } else if (type == TO) {
             type = BOTH;
-        }             
+        }
         item.setSubscriptionType(type);
         if (item.getAskSubscriptionType() == ASK_SUBSCRIBED) item.setAskSubscriptionType(NOT_SET);
         return OK;
     }
 
-    protected RosterSubscriptionMutatorResult removeWorker(RosterItem item, SubscriptionType removeSubscriptionType) {
+    protected Result removeWorker(RosterItem item, SubscriptionType removeSubscriptionType) {
         switch (removeSubscriptionType) {
             case NONE:
             case BOTH:
             case REMOVE:
-                return RosterSubscriptionMutatorResult.ILLEGAL_ARGUMENT;
+                return Result.ILLEGAL_ARGUMENT;
             case FROM:
                 return removeTo(item);
             case TO:
@@ -147,26 +158,26 @@
         }
     }
 
-    protected RosterSubscriptionMutatorResult removeTo(RosterItem item) {
+    protected Result removeTo(RosterItem item) {
         SubscriptionType type = item.getSubscriptionType();
         if (!type.includesTo()) return ALREADY_SET;
         if (type == BOTH) {
             type = FROM;
         } else if (type == TO) {
             type = NONE;
-        }             
+        }
         item.setSubscriptionType(type);
         return OK;
     }
 
-    protected RosterSubscriptionMutatorResult removeFrom(RosterItem item) {
+    protected Result removeFrom(RosterItem item) {
         SubscriptionType type = item.getSubscriptionType();
         if (!type.includesFrom()) return ALREADY_SET;
         if (type == BOTH) {
             type = TO;
         } else if (type == FROM) {
             type = NONE;
-        }             
+        }
         item.setSubscriptionType(type);
         return OK;
     }

Modified: labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/persistence/MemoryRosterManager.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/persistence/MemoryRosterManager.java?rev=704646&r1=704645&r2=704646&view=diff
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/persistence/MemoryRosterManager.java (original)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/persistence/MemoryRosterManager.java Tue Oct 14 12:50:53 2008
@@ -50,16 +50,17 @@
         mutableRoster.addItem(rosterItem);
     }
 
-    public void modifyContact(Entity jid, RosterItem rosterItem) throws RosterException {
-        if (jid == null) throw new RosterException("jid not provided");
-        Roster roster = retrieve(jid);
-        if (roster == null) throw new RosterException("roster not available for jid = " + jid.getFullQualifiedName());
+    public RosterItem getContact(Entity jidUser, Entity jidContact) throws RosterException {
+        if (jidUser == null) throw new RosterException("jid not provided");
+        Roster roster = retrieve(jidUser);
+        if (roster == null) throw new RosterException("roster not available for jid = " + jidUser.getFullQualifiedName());
+        return roster.getEntry(jidContact);
     }
 
-    public void removeContact(Entity jid, RosterItem rosterItem) throws RosterException {
-        if (jid == null) throw new RosterException("jid not provided");
-        Roster roster = retrieve(jid);
-        if (roster == null) throw new RosterException("roster not available for jid = " + jid.getFullQualifiedName());
+    public void removeContact(Entity jidUser, Entity jidContact) throws RosterException {
+        if (jidUser == null) throw new RosterException("jid not provided");
+        Roster roster = retrieve(jidUser);
+        if (roster == null) throw new RosterException("roster not available for jid = " + jidUser.getFullQualifiedName());
     }
 
     public String getServiceName() {

Modified: labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/persistence/RosterManager.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/persistence/RosterManager.java?rev=704646&r1=704645&r2=704646&view=diff
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/persistence/RosterManager.java (original)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/modules/roster/persistence/RosterManager.java Tue Oct 14 12:50:53 2008
@@ -32,8 +32,8 @@
 
     void addContact(Entity jid, RosterItem rosterItem) throws RosterException;
     
-    void modifyContact(Entity jid, RosterItem rosterItem) throws RosterException;
+    RosterItem getContact(Entity jidUser, Entity jidContact) throws RosterException;
     
-    void removeContact(Entity jid, RosterItem rosterItem) throws RosterException;
+    void removeContact(Entity jid, Entity jidContact) throws RosterException;
     
 }

Modified: labs/vysper/src/test/java/org/apache/vysper/xmpp/modules/roster/RosterSubscriptionMutatorTestCase.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/test/java/org/apache/vysper/xmpp/modules/roster/RosterSubscriptionMutatorTestCase.java?rev=704646&r1=704645&r2=704646&view=diff
==============================================================================
--- labs/vysper/src/test/java/org/apache/vysper/xmpp/modules/roster/RosterSubscriptionMutatorTestCase.java (original)
+++ labs/vysper/src/test/java/org/apache/vysper/xmpp/modules/roster/RosterSubscriptionMutatorTestCase.java Tue Oct 14 12:50:53 2008
@@ -21,7 +21,7 @@
 import org.apache.vysper.xmpp.addressing.EntityFormatException;
 import static org.apache.vysper.xmpp.modules.roster.AskSubscriptionType.*;
 import static org.apache.vysper.xmpp.modules.roster.SubscriptionType.*;
-import static org.apache.vysper.xmpp.modules.roster.RosterSubscriptionMutator.RosterSubscriptionMutatorResult.*;
+import static org.apache.vysper.xmpp.modules.roster.RosterSubscriptionMutator.Result.*;
 
 /**
  */
@@ -44,14 +44,16 @@
         checkAdd(FROM, NOT_SET, ASK_SUBSCRIBE, OK, FROM, ASK_SUBSCRIBE);
 
         // status already set
-        checkAdd(TO, ASK_SUBSCRIBED, ASK_SUBSCRIBED, ALREADY_SET, null, null);
-        checkAdd(FROM, ASK_SUBSCRIBE, ASK_SUBSCRIBE, ALREADY_SET, null, null);
-        
+        checkAdd(TO, ASK_SUBSCRIBED, ASK_SUBSCRIBED, OK, null, null);
+        checkAdd(FROM, ASK_SUBSCRIBE, ASK_SUBSCRIBE, OK, null, null);
+        checkAdd(TO, NOT_SET, ASK_SUBSCRIBE, ALREADY_SET, null, null);
+        checkAdd(FROM, NOT_SET, ASK_SUBSCRIBED, ALREADY_SET, null, null);
+
         // BOTH + pending is kind of illegal state. well anyway...
-        checkAdd(BOTH, ASK_SUBSCRIBED, ASK_SUBSCRIBED, ALREADY_SET, null, null);
-        checkAdd(BOTH, ASK_SUBSCRIBE, ASK_SUBSCRIBE, ALREADY_SET, null, null);
         checkAdd(BOTH, NOT_SET, ASK_SUBSCRIBED, ALREADY_SET, null, null);
         checkAdd(BOTH, NOT_SET, ASK_SUBSCRIBE, ALREADY_SET, null, null);
+        checkAdd(BOTH, ASK_SUBSCRIBED, ASK_SUBSCRIBED, ALREADY_SET, null, null);
+        checkAdd(BOTH, ASK_SUBSCRIBE, ASK_SUBSCRIBE, ALREADY_SET, null, null);
 
         // special cases for conflicting SUBSCRIBE/SUBSCRIBED stati
         checkAdd(NONE, ASK_SUBSCRIBED, ASK_SUBSCRIBE, OK, NONE, ASK_SUBSCRIBE);
@@ -79,6 +81,10 @@
         checkAdd(TO, ASK_SUBSCRIBED, FROM, OK, BOTH, NOT_SET);
         checkAdd(TO, ASK_SUBSCRIBE, FROM, OK, BOTH, ASK_SUBSCRIBE);
 
+        checkAdd(FROM, NOT_SET, TO, OK, BOTH, NOT_SET);
+        checkAdd(FROM, ASK_SUBSCRIBE, TO, OK, BOTH, NOT_SET);
+        checkAdd(FROM, ASK_SUBSCRIBED, TO, OK, BOTH, ASK_SUBSCRIBED);
+
     }
 
     public void testRemoveSubscription() {
@@ -87,31 +93,31 @@
 
     private void checkAdd(SubscriptionType initialSubscriptionType, AskSubscriptionType initialAskSubscriptionType,
                        SubscriptionType parameterSubscriptionType, 
-                       RosterSubscriptionMutator.RosterSubscriptionMutatorResult expectedResult,
+                       RosterSubscriptionMutator.Result expectedResult,
                        SubscriptionType expectedSubscriptionType, AskSubscriptionType expectedAskSubscriptionType) {
 
         RosterItem item = prepareItem(initialSubscriptionType, initialAskSubscriptionType);
         
         // add parameterSubscriptionType 
-        RosterSubscriptionMutator.RosterSubscriptionMutatorResult subscriptionMutatorResult = new RosterSubscriptionMutator().add(item, parameterSubscriptionType);
+        RosterSubscriptionMutator.Result subscriptionMutatorResult = new RosterSubscriptionMutator().add(item, parameterSubscriptionType);
 
         checkResult(initialSubscriptionType, initialAskSubscriptionType, expectedResult, expectedSubscriptionType, expectedAskSubscriptionType, item, subscriptionMutatorResult);
     }
 
     private void checkAdd(SubscriptionType initialSubscriptionType, AskSubscriptionType initialAskSubscriptionType,
                        AskSubscriptionType parameterAskSubscriptionType, 
-                       RosterSubscriptionMutator.RosterSubscriptionMutatorResult expectedResult,
+                       RosterSubscriptionMutator.Result expectedResult,
                        SubscriptionType expectedSubscriptionType, AskSubscriptionType expectedAskSubscriptionType) {
 
         RosterItem item = prepareItem(initialSubscriptionType, initialAskSubscriptionType);
         
         // add parameterSubscriptionType 
-        RosterSubscriptionMutator.RosterSubscriptionMutatorResult subscriptionMutatorResult = new RosterSubscriptionMutator().add(item, parameterAskSubscriptionType);
+        RosterSubscriptionMutator.Result subscriptionMutatorResult = new RosterSubscriptionMutator().add(item, parameterAskSubscriptionType);
 
         checkResult(initialSubscriptionType, initialAskSubscriptionType, expectedResult, expectedSubscriptionType, expectedAskSubscriptionType, item, subscriptionMutatorResult);
     }
 
-    private void checkResult(SubscriptionType initialSubscriptionType, AskSubscriptionType initialAskSubscriptionType, RosterSubscriptionMutator.RosterSubscriptionMutatorResult expectedResult, SubscriptionType expectedSubscriptionType, AskSubscriptionType expectedAskSubscriptionType, RosterItem item, RosterSubscriptionMutator.RosterSubscriptionMutatorResult subscriptionMutatorResult) {
+    private void checkResult(SubscriptionType initialSubscriptionType, AskSubscriptionType initialAskSubscriptionType, RosterSubscriptionMutator.Result expectedResult, SubscriptionType expectedSubscriptionType, AskSubscriptionType expectedAskSubscriptionType, RosterItem item, RosterSubscriptionMutator.Result subscriptionMutatorResult) {
         assertEquals(expectedResult, subscriptionMutatorResult);
 
         if (expectedSubscriptionType == null && expectedAskSubscriptionType == null) {



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@labs.apache.org
For additional commands, e-mail: commits-help@labs.apache.org