Fixes WAVE-417 Adds GadgetStateChange event generation for robot API.

Project: http://git-wip-us.apache.org/repos/asf/incubator-wave/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-wave/commit/c2784ad2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-wave/tree/c2784ad2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-wave/diff/c2784ad2

Branch: refs/heads/master
Commit: c2784ad28bdaa46c6224b0341e8f595f91fd7d27
Parents: 4499ce5
Author: Antonio Tenorio-Fornés <[email protected]>
Authored: Sun Apr 12 23:37:34 2015 +0300
Committer: Yuri Zelikov <[email protected]>
Committed: Sun Apr 12 23:39:19 2015 +0300

----------------------------------------------------------------------
 build.properties                                |   2 +-
 .../server/robots/passive/EventGenerator.java   | 132 ++++++++++++++-----
 2 files changed, 99 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/c2784ad2/build.properties
----------------------------------------------------------------------
diff --git a/build.properties b/build.properties
index 7f98247..86aad10 100644
--- a/build.properties
+++ b/build.properties
@@ -16,7 +16,7 @@
 # under the License.
 
 # Current versions
-waveinabox.version=0.4.0
+waveinabox.version=0.6.0
 
 # Names
 name=wave-in-a-box

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/c2784ad2/src/org/waveprotocol/box/server/robots/passive/EventGenerator.java
----------------------------------------------------------------------
diff --git a/src/org/waveprotocol/box/server/robots/passive/EventGenerator.java 
b/src/org/waveprotocol/box/server/robots/passive/EventGenerator.java
index 206a33b..b45a0f8 100644
--- a/src/org/waveprotocol/box/server/robots/passive/EventGenerator.java
+++ b/src/org/waveprotocol/box/server/robots/passive/EventGenerator.java
@@ -23,56 +23,43 @@ import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.wave.api.BlipData;
 import com.google.wave.api.Context;
+import com.google.wave.api.Gadget;
 import com.google.wave.api.data.converter.ContextResolver;
 import com.google.wave.api.data.converter.EventDataConverter;
-import com.google.wave.api.event.AnnotatedTextChangedEvent;
-import com.google.wave.api.event.DocumentChangedEvent;
-import com.google.wave.api.event.Event;
-import com.google.wave.api.event.EventType;
-import com.google.wave.api.event.FormButtonClickedEvent;
-import com.google.wave.api.event.WaveletBlipCreatedEvent;
-import com.google.wave.api.event.WaveletBlipRemovedEvent;
-import com.google.wave.api.event.WaveletParticipantsChangedEvent;
-import com.google.wave.api.event.WaveletSelfAddedEvent;
-import com.google.wave.api.event.WaveletSelfRemovedEvent;
+import com.google.wave.api.event.*;
 import com.google.wave.api.impl.EventMessageBundle;
 import com.google.wave.api.robot.Capability;
 import com.google.wave.api.robot.RobotName;
-
 import org.waveprotocol.box.server.robots.util.ConversationUtil;
 import org.waveprotocol.box.server.util.WaveletDataUtil;
-import org.waveprotocol.wave.model.conversation.Conversation;
-import org.waveprotocol.wave.model.conversation.ConversationBlip;
-import org.waveprotocol.wave.model.conversation.ConversationListenerImpl;
-import org.waveprotocol.wave.model.conversation.ObservableConversation;
-import org.waveprotocol.wave.model.conversation.ObservableConversationBlip;
-import org.waveprotocol.wave.model.conversation.WaveletBasedConversation;
-import org.waveprotocol.wave.model.document.DocHandler;
-import org.waveprotocol.wave.model.document.ObservableDocument;
+import org.waveprotocol.wave.model.conversation.*;
 import org.waveprotocol.wave.model.document.Doc.E;
 import org.waveprotocol.wave.model.document.Doc.N;
 import org.waveprotocol.wave.model.document.Doc.T;
+import org.waveprotocol.wave.model.document.DocHandler;
+import org.waveprotocol.wave.model.document.ObservableDocument;
 import org.waveprotocol.wave.model.document.indexed.DocumentEvent;
 import 
org.waveprotocol.wave.model.document.indexed.DocumentEvent.AnnotationChanged;
+import 
org.waveprotocol.wave.model.document.indexed.DocumentEvent.AttributesModified;
 import 
org.waveprotocol.wave.model.document.indexed.DocumentEvent.ContentInserted;
-import org.waveprotocol.wave.model.document.raw.impl.Element;
+import org.waveprotocol.wave.model.document.raw.impl.Node;
 import org.waveprotocol.wave.model.operation.OperationException;
 import org.waveprotocol.wave.model.operation.SilentOperationSink;
 import 
org.waveprotocol.wave.model.operation.wave.BasicWaveletOperationContextFactory;
 import org.waveprotocol.wave.model.operation.wave.TransformedWaveletDelta;
 import org.waveprotocol.wave.model.operation.wave.WaveletBlipOperation;
 import org.waveprotocol.wave.model.operation.wave.WaveletOperation;
-import org.waveprotocol.wave.model.wave.ObservableWavelet;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.model.wave.ParticipationHelper;
-import org.waveprotocol.wave.model.wave.WaveletListener;
+import org.waveprotocol.wave.model.wave.*;
 import org.waveprotocol.wave.model.wave.data.ObservableWaveletData;
 import org.waveprotocol.wave.model.wave.opbased.OpBasedWavelet;
 import org.waveprotocol.wave.model.wave.opbased.WaveletListenerImpl;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Generates Robot API Events from operations applied to a Wavelet.
@@ -87,7 +74,7 @@ import java.util.Map;
  * <li>DocumentChanged (DONE)</li>
  * <li>AnnotatedTextChanged (DONE)</li>
  * <li>FormButtonClicked (TBD)</li>
- * <li>GadgetStateChanged (TBD)</li>
+ * <li>GadgetStateChanged (DONE)</li>
  * <li>BlipContributorChanged (TBD)</li>
  * <li>WaveletTagsChanged (TBD)</li>
  * <li>WaveletTitleChanged (TBD)</li>
@@ -258,13 +245,19 @@ public class EventGenerator {
      */
     private boolean documentChangedEventGenerated;
 
+    private EventDataConverter converter;
+    private Wavelet wavelet;
+
     public EventGeneratingDocumentHandler(ObservableDocument doc, 
ConversationBlip blip,
         Map<EventType, Capability> capabilities, EventMessageBundle messages,
-        ParticipantId deltaAuthor, Long deltaTimestamp) {
+        ParticipantId deltaAuthor, Long deltaTimestamp, Wavelet wavelet,
+        EventDataConverter converter) {
       this.doc = doc;
       this.blip = blip;
       this.capabilities = capabilities;
       this.messages = messages;
+      this.converter = converter;
+      this.wavelet = wavelet;
       setAuthorAndTimeStamp(deltaAuthor, deltaTimestamp);
     }
 
@@ -283,10 +276,64 @@ public class EventGenerator {
             addEvent(apiEvent, capabilities, blip.getId(), messages);
           }
         } else {
+          // used to distinguish between attribute changes and gadget state
+          // changes
+          Boolean gadgetStateChangeEvent = false;
+          if (eventComponent.getType() == DocumentEvent.Type.ATTRIBUTES) {
+            if (capabilities.containsKey(EventType.GADGET_STATE_CHANGED)) {
+              Map<String, String> oldState = new HashMap<>();
+              Integer index = -1;
+              try {
+                AttributesModified<N, E, T> attributesModified =
+                    (AttributesModified<N, E, T>) eventComponent;
+                // When a gadget state changes, the AttributesModifies event 
has
+                // always
+                // an oldValue map of the form {"value", something} (key is
+                // always value).
+                // To obtain the key of the changed state, the attribute "name"
+                // has to be obtained
+                // from the Element of the AttributesModified event.
+                String name =
+                    ((org.waveprotocol.wave.model.document.raw.impl.Element) 
attributesModified
+                        .getElement()).getAttribute("name");
+                String oldValue = 
attributesModified.getOldValues().get("value");
+                if (name != null || oldValue != null) {
+                  oldState.put(name, oldValue);
+                }
+                BlipData b = converter.toBlipData(blip, wavelet, messages);
+                Map<Integer, com.google.wave.api.Element> elements = 
b.getElements();
+                Set<Integer> keys = elements.keySet();
+                // The gadget element provided by the eventComponent
+                org.waveprotocol.wave.model.document.raw.impl.Element 
rawGadget =
+                    ((Node) 
attributesModified.getElement()).getParentElement();
+                for (Integer key : keys) {
+                  try {
+                    Gadget gadget = (Gadget) elements.get(key);
+                    if (sameGadgets(rawGadget, gadget)) {
+                      index = key;
+                      break;
+                    }
+                  } catch (ClassCastException e) {
+                    // if it is not a gadget we do not compare them
+                  }
+                }
+              } catch (ClassCastException e) {
+                e.printStackTrace();
+              }
+              if (oldState.size() != 0 && index != -1) {
+                // if the attribute changed belongs to a gadget
+                gadgetStateChangeEvent = true;
+                final GadgetStateChangedEvent gadgetEvent =
+                    new GadgetStateChangedEvent(null, messages, 
deltaAuthor.getAddress(),
+                        deltaTimestamp, blip.getId(), index, oldState);
+                addEvent(gadgetEvent, capabilities, blip.getId(), messages);
+              }
+            }
+          }
           if (capabilities.containsKey(EventType.FORM_BUTTON_CLICKED)) {
             if (eventComponent.getType() == 
DocumentEvent.Type.CONTENT_INSERTED) {
               ContentInserted<N, E, T> contentInserted = (ContentInserted<N, 
E, T>) eventComponent;
-              Element elementInserted = ((Element) 
contentInserted.getSubtreeElement());
+              org.waveprotocol.wave.model.document.raw.impl.Element 
elementInserted = ((org.waveprotocol.wave.model.document.raw.impl.Element) 
contentInserted.getSubtreeElement());
               if (elementInserted.getTagName().equals("click")) {
                 FormButtonClickedEvent buttonClickedEvent =
                     new FormButtonClickedEvent(null, null,
@@ -299,9 +346,10 @@ public class EventGenerator {
 
           } else
           if (capabilities.containsKey(EventType.DOCUMENT_CHANGED)
-              && !documentChangedEventGenerated) {
-            DocumentChangedEvent apiEvent = new DocumentChangedEvent(
-                null, null, deltaAuthor.getAddress(), deltaTimestamp, 
blip.getId());
+              && !documentChangedEventGenerated && !gadgetStateChangeEvent) {
+            DocumentChangedEvent apiEvent =
+                new DocumentChangedEvent(null, null, deltaAuthor.getAddress(), 
deltaTimestamp,
+                    blip.getId());
             addEvent(apiEvent, capabilities, blip.getId(), messages);
             // Only one documentChangedEvent should be generated per bundle.
             documentChangedEventGenerated = true;
@@ -324,6 +372,21 @@ public class EventGenerator {
       this.deltaAuthor = author;
       this.deltaTimestamp = timestamp;
     }
+
+    /**
+     * Check if an {@link 
org.waveprotocol.wave.model.document.raw.impl.Element}
+     * is and a {@link Gadget}
+     *
+     * @param rawElement
+     * @param element
+     * @return
+     */
+    private boolean 
sameGadgets(org.waveprotocol.wave.model.document.raw.impl.Element rawElement,
+        Gadget element) {
+      String ifr1 = rawElement.getAttribute("ifr");
+      String ifr2 = element.getProperty("ifr");
+      return (ifr1 != null && ifr1.equals(ifr2));
+    }
   }
 
   /**
@@ -473,7 +536,7 @@ public class EventGenerator {
           // Check if we need to attach a doc handler.
           if ((op instanceof WaveletBlipOperation)) {
             attachDocHandler(conversation, op, docHandlers, capabilities, 
messages,
-                delta.getAuthor(), timestamp);
+                delta.getAuthor(), timestamp, wavelet, converter);
           }
           op.apply(snapshot);
         }
@@ -515,7 +578,7 @@ public class EventGenerator {
   private void attachDocHandler(ObservableConversation conversation, 
WaveletOperation op,
       Map<String, EventGeneratingDocumentHandler> docHandlers,
       Map<EventType, Capability> capabilities, EventMessageBundle messages,
-      ParticipantId deltaAuthor, long timestamp) {
+      ParticipantId deltaAuthor, long timestamp, Wavelet wavelet, 
EventDataConverter converter) {
     WaveletBlipOperation blipOp = (WaveletBlipOperation) op;
     String blipId = blipOp.getBlipId();
     // Ignoring the documents outside the conversation such as tags
@@ -527,8 +590,9 @@ public class EventGenerator {
       EventGeneratingDocumentHandler docHandler = docHandlers.get(blipId1);
       if (docHandler == null) {
         ObservableDocument doc = (ObservableDocument) blip.getContent();
-        docHandler = new EventGeneratingDocumentHandler(
-            doc, blip, capabilities, messages, deltaAuthor, timestamp);
+        docHandler =
+            new EventGeneratingDocumentHandler(doc, blip, capabilities, 
messages, deltaAuthor,
+                timestamp, wavelet, converter);
         doc.addListener(docHandler);
         docHandlers.put(blipId1, docHandler);
       } else {

Reply via email to