http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/operations/DocumentModifyService.java
----------------------------------------------------------------------
diff --git 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/DocumentModifyService.java
 
b/wave/src/main/java/org/waveprotocol/box/server/robots/operations/DocumentModifyService.java
deleted file mode 100644
index 166c360..0000000
--- 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/DocumentModifyService.java
+++ /dev/null
@@ -1,545 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.operations;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
-import com.google.wave.api.Element;
-import com.google.wave.api.Gadget;
-import com.google.wave.api.InvalidRequestException;
-import com.google.wave.api.JsonRpcConstant.ParamsProperty;
-import com.google.wave.api.OperationRequest;
-import com.google.wave.api.Range;
-import com.google.wave.api.data.ApiView;
-import com.google.wave.api.data.DocumentHitIterator;
-import com.google.wave.api.data.ElementSerializer;
-import com.google.wave.api.impl.DocumentModifyAction;
-import com.google.wave.api.impl.DocumentModifyAction.BundledAnnotation;
-import com.google.wave.api.impl.DocumentModifyAction.ModifyHow;
-import com.google.wave.api.impl.DocumentModifyQuery;
-
-import org.waveprotocol.box.server.robots.OperationContext;
-import org.waveprotocol.box.server.robots.util.OperationUtil;
-import org.waveprotocol.wave.model.conversation.ObservableConversation;
-import org.waveprotocol.wave.model.document.Doc;
-import org.waveprotocol.wave.model.document.Document;
-import org.waveprotocol.wave.model.document.RangedAnnotation;
-import org.waveprotocol.wave.model.document.util.LineContainers;
-import org.waveprotocol.wave.model.document.util.Point;
-import org.waveprotocol.wave.model.document.util.XmlStringBuilder;
-import org.waveprotocol.wave.model.gadget.GadgetXmlUtil;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.model.wave.opbased.OpBasedWavelet;
-
-import java.util.Map;
-
-/**
- * Implements the "document.modify" operations.
- *
- * <p>
- * The documentModify operation has three bits: the where: where is the
- * modification applied. a range, index, element or annotation can be 
specified.
- * Any of these is the converted to a range. If nothing appropriate is
- * specified, the entire document is taken. the how: do we insert (before),
- * append or replace? the what: what is inserted/replaced.
- *
- * @author ljvder...@google.com (Lennard de Rijk)
- */
-public class DocumentModifyService implements OperationService {
-
-  @Override
-  public void execute(
-      OperationRequest operation, OperationContext context, ParticipantId 
participant)
-      throws InvalidRequestException {
-    String blipId = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.BLIP_ID);
-
-    DocumentModifyAction modifyAction =
-        OperationUtil.getRequiredParameter(operation, 
ParamsProperty.MODIFY_ACTION);
-
-    OpBasedWavelet wavelet = context.openWavelet(operation, participant);
-    ObservableConversation conversation =
-        context.openConversation(operation, participant).getRoot();
-    Document doc = context.getBlip(conversation, blipId).getContent();
-
-    ApiView view = new ApiView(doc, wavelet);
-    DocumentHitIterator hitIterator = getDocumentHitIterator(operation, view);
-
-    switch (modifyAction.getModifyHow()) {
-      case ANNOTATE:
-        annotate(operation, doc, view, hitIterator, modifyAction);
-        break;
-      case CLEAR_ANNOTATION:
-        clearAnnotation(operation, doc, view, hitIterator, modifyAction);
-        break;
-      case DELETE:
-        delete(operation, view, hitIterator);
-        break;
-      case INSERT:
-        insert(operation, doc, view, hitIterator, modifyAction);
-        break;
-      case INSERT_AFTER:
-        insertAfter(operation, doc, view, hitIterator, modifyAction);
-        break;
-      case REPLACE:
-        replace(operation, doc, view, hitIterator, modifyAction);
-        break;
-      case UPDATE_ELEMENT:
-        updateElement(operation, doc, view, hitIterator, modifyAction);
-        break;
-      default:
-        throw new UnsupportedOperationException(
-            "Unsupported ModifyHow " + modifyAction.getModifyHow());
-    }
-  }
-
-  /**
-   * Returns the {@link DocumentHitIterator} for the area that needs to be
-   * modified as specified in the robot operation.
-   *
-   * @param operation the operation that specifies where the modifications need
-   *        to be applied.
-   * @param view the {@link ApiView} of the document that needs to be modified.
-   * @throws InvalidRequestException if more than one "where" parameter is
-   *         specified.
-   */
-  private DocumentHitIterator getDocumentHitIterator(OperationRequest 
operation, ApiView view)
-      throws InvalidRequestException {
-    Range range = OperationUtil.getOptionalParameter(operation, 
ParamsProperty.RANGE);
-    Integer index = OperationUtil.getOptionalParameter(operation, 
ParamsProperty.INDEX);
-    DocumentModifyQuery query =
-        OperationUtil.getOptionalParameter(operation, 
ParamsProperty.MODIFY_QUERY);
-
-    DocumentHitIterator hitIterator;
-    if (range != null) {
-      if (index != null || query != null) {
-        throw new InvalidRequestException(
-            "At most one parameter out of RANGE, INDEX and MODIFY_QUERY must 
be specified",
-            operation);
-      }
-      // Use the specified range
-      hitIterator = new DocumentHitIterator.Singleshot(range);
-    } else if (index != null) {
-      if (query != null) { // range is null.
-        throw new InvalidRequestException(
-            "At most one parameter out of RANGE, INDEX and MODIFY_QUERY must 
be specified",
-            operation);
-      }
-      // Use exactly the location of the index
-      hitIterator = new DocumentHitIterator.Singleshot(new Range(index, index 
+ 1));
-    } else if (query != null) { // range and index are both null.
-      // Use the query
-      hitIterator = new DocumentHitIterator.ElementMatcher(
-          view, query.getElementMatch(), query.getRestrictions(), 
query.getMaxRes());
-    } else {
-      // Take entire document since nothing appropriate was specified
-      hitIterator = new DocumentHitIterator.Singleshot(new Range(0, 
view.apiContents().length()));
-    }
-    return hitIterator;
-  }
-
-  /**
-   * Annotates the given ranges of the document as indicated by the
-   * {@link DocumentModifyAction}.
-   *
-   * @param operation the operation to execute.
-   * @param doc the document to annotate.
-   * @param view the view of the document.
-   * @param hitIterator iterates over the ranges to annotate, specified in
-   *        {@link ApiView} offset.
-   * @param modifyAction the {@link DocumentModifyAction} specifying what the
-   *        annotation is.
-   * @throws InvalidRequestException if the annotation could not be set.
-   */
-  private void annotate(OperationRequest operation, Document doc, ApiView view,
-      DocumentHitIterator hitIterator, DocumentModifyAction modifyAction)
-      throws InvalidRequestException {
-    Preconditions.checkArgument(
-        modifyAction.getModifyHow() == ModifyHow.ANNOTATE, "This method only 
supports ANNOTATE");
-
-    String annotationKey = modifyAction.getAnnotationKey();
-
-    int valueIndex = 0;
-    Range range = hitIterator.next();
-    while (range != null) {
-      int start = view.transformToXmlOffset(range.getStart());
-      int end = view.transformToXmlOffset(range.getEnd());
-      setDocumentAnnotation(
-          operation, doc, start, end, annotationKey, 
modifyAction.getValue(valueIndex));
-
-      valueIndex++;
-      range = hitIterator.next();
-    }
-  }
-
-  /**
-   * Clears the annotation for the given ranges of the document as indicated by
-   * the {@link DocumentModifyAction}.
-   *
-   * @param operation the operation to execute.
-   * @param doc the document to annotate.
-   * @param view the view of the document.
-   * @param hitIterator iterates over the ranges to remove the annotation from,
-   *        specified in {@link ApiView} offset.
-   * @param modifyAction the {@link DocumentModifyAction} specifying what the
-   *        key of the annotation is annotation is.
-   * @throws InvalidRequestException if the annotation could not be set.
-   */
-  private void clearAnnotation(OperationRequest operation, Document doc, 
ApiView view,
-      DocumentHitIterator hitIterator, DocumentModifyAction modifyAction)
-      throws InvalidRequestException {
-    Preconditions.checkArgument(modifyAction.getModifyHow() == 
ModifyHow.CLEAR_ANNOTATION,
-        "This method only supports CLEAR_ANNOTATION");
-
-    String annotationKey = modifyAction.getAnnotationKey();
-
-    Range range = hitIterator.next();
-    while (range != null) {
-      int start = view.transformToXmlOffset(range.getStart());
-      int end = view.transformToXmlOffset(range.getEnd());
-      setDocumentAnnotation(operation, doc, start, end, annotationKey, null);
-
-      range = hitIterator.next();
-    }
-  }
-
-  /**
-   * Sets the annotation for a document.
-   *
-   * @param operation the operation requesting the annotation to be set.
-   * @param doc the document to change the annotation in.
-   * @param start where the annotation should start.
-   * @param end where the annotation should end.
-   * @param key the key of the annotation.
-   * @param value the value of the annotation.
-   * @throws InvalidRequestException if the annotation could not be set.
-   */
-  private void setDocumentAnnotation(
-      OperationRequest operation, Document doc, int start, int end, String 
key, String value)
-      throws InvalidRequestException {
-    try {
-      doc.setAnnotation(start, end, key, value);
-    } catch (IndexOutOfBoundsException e) {
-      throw new InvalidRequestException(
-          "Can't set annotation for out of bounds indices " + e.getMessage(), 
operation, e);
-    }
-  }
-
-  /**
-   * Deletes ranges of elements from a document as specified by the iterator.
-   *
-   * @param operation the operation to execute.
-   * @param view the view of the document.
-   * @param hitIterator iterates over the ranges of elements to delete.
-   * @throws InvalidRequestException if the specified range was invalid.
-   */
-  private void delete(OperationRequest operation, ApiView view, 
DocumentHitIterator hitIterator)
-      throws InvalidRequestException {
-    Range range = hitIterator.next();
-    while (range != null) {
-      int start = range.getStart();
-      int end = range.getEnd();
-
-      if (start == 0) {
-        // Can't delete the first new line.
-        start = 1;
-      }
-
-      if (start >= end) {
-        throw new InvalidRequestException(
-            "Invalid range specified, " + start + ">=" + end, operation);
-      }
-
-      // Delete using the view.
-      view.delete(start, end);
-      // Shift the iterator to match the updated document.
-      hitIterator.shift(start, end - start);
-
-      range = hitIterator.next();
-    }
-  }
-
-  /**
-   * Inserts elements at the position specified by the hitIterator.
-   *
-   * @param operation the operation that wants to insert elements.
-   * @param doc the document to insert elements in.
-   * @param view the {@link ApiView} of that document.
-   * @param hitIterator the iterator over the places where to insert.
-   * @param modifyAction the action that specifies what to insert.
-   * @throws InvalidRequestException if something goes wrong.
-   */
-  private void insert(OperationRequest operation, Document doc, ApiView view,
-      DocumentHitIterator hitIterator, DocumentModifyAction modifyAction)
-      throws InvalidRequestException {
-    int valueIndex = 0;
-    Range range = hitIterator.next();
-    while (range != null) {
-      int insertAt = range.getStart();
-
-      int inserted = insertInto(operation, doc, view, insertAt, modifyAction, 
valueIndex);
-      hitIterator.shift(insertAt, inserted);
-
-      valueIndex++;
-      range = hitIterator.next();
-    }
-  }
-
-  /**
-   * Inserts elements after the position specified by the hitIterator.
-   *
-   * @param operation the operation that wants to insert elements.
-   * @param doc the document to insert elements in.
-   * @param view the {@link ApiView} of that document.
-   * @param hitIterator the iterator over the places where to insert.
-   * @param modifyAction the action that specifies what to insert.
-   * @throws InvalidRequestException if something goes wrong.
-   */
-  private void insertAfter(OperationRequest operation, Document doc, ApiView 
view,
-      DocumentHitIterator hitIterator, DocumentModifyAction modifyAction)
-      throws InvalidRequestException {
-    int valueIndex = 0;
-    Range range = hitIterator.next();
-    while (range != null) {
-      int insertAt = range.getEnd();
-
-      int inserted = insertInto(operation, doc, view, insertAt, modifyAction, 
valueIndex);
-      hitIterator.shift(insertAt, inserted);
-
-      valueIndex++;
-      range = hitIterator.next();
-    }
-  }
-
-  /**
-   * Replaces elements at the position specified by the hitIterator with the
-   * elements specified in the {@link DocumentModifyAction}.
-   *
-   * @param operation the operation that wants to replace elements.
-   * @param doc the document to replace elements in.
-   * @param view the {@link ApiView} of that document.
-   * @param hitIterator the iterator over the places where to replace elements.
-   * @param modifyAction the action that specifies what to replace the elements
-   *        with.
-   * @throws InvalidRequestException if something goes wrong.
-   */
-  private void replace(OperationRequest operation, Document doc, ApiView view,
-      DocumentHitIterator hitIterator, DocumentModifyAction modifyAction)
-      throws InvalidRequestException {
-    int valueIndex = 0;
-    Range range = hitIterator.next();
-    while (range != null) {
-      int replaceAt = range.getStart();
-
-      int numInserted = insertInto(operation, doc, view, replaceAt, 
modifyAction, valueIndex);
-
-      // Remove the text after what was inserted (so it looks like it has been
-      // replaced).
-      view.delete(replaceAt + numInserted, range.getEnd() + numInserted);
-
-      // Shift the iterator from the start of the replacement with the amount 
of
-      // characters that have been added.
-      int numRemoved = Math.min(0, range.getStart() - range.getEnd());
-      hitIterator.shift(replaceAt, numInserted + numRemoved);
-
-      valueIndex++;
-      range = hitIterator.next();
-    }
-  }
-
-  /**
-   * Inserts elements into the document at a specified location.
-   *
-   * @param operation the operation that wants to insert elements.
-   * @param doc the document to insert elements in.
-   * @param view the {@link ApiView} of that document.
-   * @param insertAt the {@link ApiView} value of where to insert elements.
-   * @param modifyAction the action that specifies what to insert.
-   * @param valueIndex the index to use for
-   *        {@link DocumentModifyAction#getValue(int)}, to find out what to
-   *        insert.
-   * @throws InvalidRequestException if something goes wrong.
-   */
-  private int insertInto(OperationRequest operation, Document doc, ApiView 
view, int insertAt,
-      DocumentModifyAction modifyAction, int valueIndex) throws 
InvalidRequestException {
-
-    if (modifyAction.hasTextAt(valueIndex)) {
-      String toInsert = modifyAction.getValue(valueIndex);
-
-      if (insertAt == 0) {
-        // Make sure that we have a newline as first character.
-        if (!toInsert.isEmpty() && toInsert.charAt(0) != '\n') {
-          toInsert = '\n' + toInsert;
-        }
-      }
-
-      // Insert text.
-      view.insert(insertAt, toInsert);
-
-      // Do something with annotations?
-      if (modifyAction.getBundledAnnotations() != null) {
-        int annotationStart = view.transformToXmlOffset(insertAt);
-        int annotationEnd = view.transformToXmlOffset(insertAt + 
toInsert.length());
-
-        for (RangedAnnotation<String> annotation :
-            doc.rangedAnnotations(annotationStart, annotationEnd, null)) {
-          setDocumentAnnotation(
-              operation, doc, annotationStart, annotationEnd, 
annotation.key(), null);
-        }
-
-        for (BundledAnnotation ia : modifyAction.getBundledAnnotations()) {
-          setDocumentAnnotation(operation, doc, annotationStart, 
annotationEnd, ia.key, ia.value);
-        }
-      }
-      return toInsert.length();
-    } else {
-      Element element = modifyAction.getElement(valueIndex);
-      if (element != null) {
-        if (element.isGadget()) {
-          Gadget gadget = (Gadget) element;
-          XmlStringBuilder xml =
-              GadgetXmlUtil.constructXml(gadget.getUrl(), "", 
gadget.getAuthor(), null,
-                  gadget.getProperties());
-          // TODO (Yuri Z.) Make it possible to specify a location to insert 
the
-          // gadget and implement insertion at the specified location.
-          LineContainers.appendLine(doc, xml);
-        } else if (element.isFormElement()) {
-          XmlStringBuilder xml = ElementSerializer.apiElementToXml(element);
-          LineContainers.appendLine(doc, xml);
-        } else {
-          // TODO(ljvderijk): Inserting other elements.
-          throw new UnsupportedOperationException(
-              "Can't insert other elements than text and gadgets at the 
moment");
-        }
-      }
-      // should return 1 since elements have a length of 1 in the ApiView;
-      return 1;
-    }
-  }
-
-  /**
-   * Updates elements in the document.
-   * <b>Note</b>: Only gadget elements are supported, for now.
-   *
-   * @param operation the operation the operation that wants to update 
elements.
-   * @param doc the document to update elements in.
-   * @param view the {@link ApiView} of that document.
-   * @param hitIterator the iterator over the places where to update elements.
-   * @param modifyAction the action that specifies what to update.
-   * @throws InvalidRequestException if something goes wrong.
-   */
-  private void updateElement(OperationRequest operation, Document doc, ApiView 
view,
-      DocumentHitIterator hitIterator, DocumentModifyAction modifyAction)
-      throws InvalidRequestException {
-    Range range = null;
-    for (int index = 0; ((range = hitIterator.next()) != null); ++index) {
-      Element element = modifyAction.getElement(index);
-      if (element != null) {
-        if (element.isGadget()) {
-          int xmlStart = view.transformToXmlOffset(range.getStart());
-          Doc.E docElem = Point.elementAfter(doc, doc.locate(xmlStart));
-          updateExistingGadgetElement(doc, docElem, element);
-        } else {
-          // TODO (Yuri Z.) Updating other elements.
-          throw new UnsupportedOperationException(
-              "Can't update other elements than gadgets at the moment");
-        }
-      }
-    }
-  }
-
-  /**
-   * Updates the existing gadget element properties.
-   *
-   * @param doc the document to update elements in.
-   * @param existingElement the gadget element to update.
-   * @param element the element that describes what existingElement should be
-   *        updated with.
-   * @throws InvalidRequestException
-   */
-  private void updateExistingGadgetElement(Document doc, Doc.E existingElement,
-      Element element) throws InvalidRequestException {
-    Preconditions.checkArgument(element.isGadget(),
-        "Called with non-gadget element type %s", element.getType());
-
-    String url = element.getProperty("url");
-    if (url != null) {
-      doc.setElementAttribute(existingElement, "url", url);
-    }
-    Map<String, Doc.E> children = Maps.newHashMap();
-    for (Doc.N child = doc.getFirstChild(existingElement); child != null; 
child =
-        doc.getNextSibling(child)) {
-      Doc.E childAsElement = doc.asElement(child);
-      if (childAsElement != null) {
-        String key = doc.getTagName(childAsElement);
-        if (key.equals("state")) {
-          key = key + " " + doc.getAttributes(childAsElement).get("name");
-        }
-        children.put(key, childAsElement);
-      }
-    }
-
-    for (Map.Entry<String, String> property : 
element.getProperties().entrySet()) {
-      // TODO (Yuri Z.) Support updating gadget metadata (author, title, 
thumbnail...)
-      // and user preferences.
-      String key = null;
-      String tag = null;
-      if (property.getKey().equals("title") || 
property.getKey().equals("thumbnail")
-          || property.getKey().equals("author")) {
-        key = property.getKey();
-        tag = property.getKey();
-      } else if (!property.getKey().equals("name") && 
!property.getKey().equals("pref")
-          && !property.getKey().equals("url")) {
-        // A state variable.
-        key = "state " + property.getKey();
-        tag = "state";
-      } else {
-        continue;
-      }
-
-      String val = property.getValue();
-      Doc.E child = children.get(key);
-      if (val == null) {
-        // Delete the property if value is null.
-        if (child == null) {
-          // Property does not exist, skipping.
-          continue;
-        }
-        doc.deleteNode(child);
-      } else {
-        if (child != null) {
-          if (tag.equals("state")) {
-            doc.setElementAttribute(child, "value", val);
-          } else {
-            doc.emptyElement(child);
-            Point<Doc.N> point = Point.<Doc.N> inElement(child, null);
-            doc.insertText(point, val);
-          }
-        } else {
-          XmlStringBuilder xml = 
GadgetXmlUtil.constructStateXml(property.getKey(), val);
-          doc.insertXml(Point.<Doc.N> inElement(existingElement, null), xml);
-        }
-      }
-    }
-  }
-
-  public static DocumentModifyService create() {
-    return new DocumentModifyService();
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ExportAttachmentService.java
----------------------------------------------------------------------
diff --git 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ExportAttachmentService.java
 
b/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ExportAttachmentService.java
deleted file mode 100644
index 37ad048..0000000
--- 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ExportAttachmentService.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.operations;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.inject.Inject;
-import com.google.protobuf.ByteString;
-import com.google.wave.api.InvalidRequestException;
-import com.google.wave.api.JsonRpcConstant.ParamsProperty;
-import com.google.wave.api.OperationRequest;
-import com.google.wave.api.impl.RawAttachmentData;
-
-import org.waveprotocol.box.server.robots.OperationContext;
-import org.waveprotocol.wave.model.id.InvalidIdException;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.box.server.attachment.AttachmentService;
-import org.waveprotocol.box.attachment.AttachmentMetadata;
-import org.waveprotocol.wave.media.model.AttachmentId;
-import org.waveprotocol.wave.util.logging.Log;
-import org.waveprotocol.box.server.robots.util.OperationUtil;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Map;
-
-/**
- * {@link OperationService} for the "exportAttachment" operation.
- *
- * @author akapla...@gmail.com (Andrew Kaplanov)
- */
-public class ExportAttachmentService implements OperationService {
-  private static final Log LOG = Log.get(ExportAttachmentService.class);
-
-  private final AttachmentService attachmentService;
-
-  @Inject
-  private ExportAttachmentService(AttachmentService attachmentSerive) {
-    this.attachmentService = attachmentSerive;
-  }
-
-  @Override
-  public void execute(OperationRequest operation, OperationContext context, 
ParticipantId participant)
-      throws InvalidRequestException {
-    AttachmentId attachmentId;
-    try {
-      attachmentId =  
AttachmentId.deserialise(OperationUtil.<String>getRequiredParameter(operation,
-          ParamsProperty.ATTACHMENT_ID));
-    } catch (InvalidIdException ex) {
-      throw new InvalidRequestException("Invalid id", operation, ex);
-    }
-    AttachmentMetadata meta;
-    byte[] data;
-    try {
-      meta = attachmentService.getMetadata(attachmentId);
-      data = 
readInputStreamToBytes(attachmentService.getAttachment(attachmentId).getInputStream());
-    } catch (IOException ex) {
-      LOG.info("Get attachment", ex);
-      context.constructErrorResponse(operation, ex.toString());
-      return;
-    }
-    RawAttachmentData attachment = new RawAttachmentData(meta.getFileName(), 
meta.getCreator(),
-        data);
-    Map<ParamsProperty, Object> parameters =
-      ImmutableMap.<ParamsProperty, Object> of(ParamsProperty.ATTACHMENT_DATA, 
attachment);
-    context.constructResponse(operation, parameters);
-  }
-
-  private static byte[] readInputStreamToBytes(InputStream in) throws 
IOException {
-    ByteArrayOutputStream out = new ByteArrayOutputStream();
-    byte[] buffer = new byte[256];
-    int length;
-    while ((length = in.read(buffer)) != -1) {
-      out.write(buffer, 0, length);
-    }
-    return out.toByteArray();
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ExportDeltasService.java
----------------------------------------------------------------------
diff --git 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ExportDeltasService.java
 
b/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ExportDeltasService.java
deleted file mode 100644
index 3df5549..0000000
--- 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ExportDeltasService.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.operations;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.protobuf.InvalidProtocolBufferException;
-import com.google.wave.api.ApiIdSerializer;
-import com.google.wave.api.InvalidRequestException;
-import com.google.wave.api.JsonRpcConstant.ParamsProperty;
-import com.google.wave.api.OperationRequest;
-import com.google.wave.api.impl.RawDeltasListener;
-
-import org.waveprotocol.wave.model.id.InvalidIdException;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.util.logging.Log;
-import org.waveprotocol.wave.model.id.WaveId;
-import org.waveprotocol.wave.model.id.WaveletId;
-import org.waveprotocol.wave.model.id.WaveletName;
-import org.waveprotocol.wave.model.version.HashedVersion;
-import org.waveprotocol.wave.federation.Proto.ProtocolWaveletDelta;
-import org.waveprotocol.wave.model.operation.wave.TransformedWaveletDelta;
-import org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion;
-import org.waveprotocol.box.server.robots.util.OperationUtil;
-import org.waveprotocol.box.server.common.CoreWaveletOperationSerializer;
-import org.waveprotocol.box.server.robots.OperationContext;
-import org.waveprotocol.box.common.Receiver;
-
-import java.util.Map;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * {@link OperationService} for the "exportDeltas" operation.
- *
- * @author akapla...@gmail.com (Andrew Kaplanov)
- */
-public class ExportDeltasService implements OperationService {
-  private static final Log LOG = Log.get(ExportDeltasService.class);
-
-  private static final int GET_HISTORY_BYTES_LENGTH_LIMIT = 1000000;
-
-  private ExportDeltasService() {
-  }
-
-  public static ExportDeltasService create() {
-    return new ExportDeltasService();
-  }
-
-  @Override
-  public void execute(final OperationRequest operation, final OperationContext 
context, ParticipantId participant)
-      throws InvalidRequestException {
-    WaveId waveId;
-    WaveletId waveletId;
-    HashedVersion startVersion;
-    HashedVersion endVersion;
-    try {
-      waveId = ApiIdSerializer.instance().deserialiseWaveId(
-        OperationUtil.<String>getRequiredParameter(operation, 
ParamsProperty.WAVE_ID));
-      waveletId = ApiIdSerializer.instance().deserialiseWaveletId(
-        OperationUtil.<String>getRequiredParameter(operation, 
ParamsProperty.WAVELET_ID));
-    } catch (InvalidIdException ex) {
-      throw new InvalidRequestException("Invalid id", operation, ex);
-    }
-    startVersion = getVersionParameter(operation, ParamsProperty.FROM_VERSION);
-    endVersion = getVersionParameter(operation, ParamsProperty.TO_VERSION);
-    WaveletName waveletName = WaveletName.of(waveId, waveletId);
-    getDeltas(context, waveletName, participant, startVersion, endVersion, new 
RawDeltasListener() {
-
-          @Override
-          public void onSuccess(List<byte[]> rawDeltas, byte[] 
rawTargetVersion) {
-            Map<ParamsProperty, Object> data = ImmutableMap.<ParamsProperty, 
Object> of(
-              ParamsProperty.RAW_DELTAS,  rawDeltas,
-              ParamsProperty.TARGET_VERSION, rawTargetVersion);
-            context.constructResponse(operation, data);
-          }
-
-          @Override
-          public void onFailire(String message) {
-            context.constructErrorResponse(operation, message);
-          }
-        });
-  }
-
-  private void getDeltas(OperationContext context, WaveletName waveletName,
-      ParticipantId participant, HashedVersion fromVersion, HashedVersion 
toVersion,
-      RawDeltasListener listener) throws InvalidRequestException {
-    final List<byte[]> deltaBytes = new LinkedList<byte[]>();
-    final AtomicReference<HashedVersion> version = new 
AtomicReference<HashedVersion>();
-    final AtomicInteger length = new AtomicInteger(0);
-    context.getDeltas(waveletName, participant, fromVersion, toVersion, new 
Receiver<TransformedWaveletDelta>() {
-
-          @Override
-          public boolean put(TransformedWaveletDelta delta) {
-            ProtocolWaveletDelta protoDelta = 
CoreWaveletOperationSerializer.serialize(delta);
-            byte[] bytes = protoDelta.toByteArray();
-            deltaBytes.add(bytes);
-            version.set(delta.getResultingVersion());
-            return length.addAndGet(bytes.length) < 
GET_HISTORY_BYTES_LENGTH_LIMIT;
-          }
-        });
-    listener.onSuccess(deltaBytes, 
CoreWaveletOperationSerializer.serialize(version.get()).toByteArray());
-  }
-
-  private HashedVersion getVersionParameter(OperationRequest operation, 
ParamsProperty parameter)
-      throws InvalidRequestException {
-    byte[] bytes = OperationUtil.<byte[]>getRequiredParameter(
-          operation, parameter);
-    ProtocolHashedVersion protoVersion;
-    try {
-      protoVersion = ProtocolHashedVersion.parseFrom(bytes);
-    } catch (InvalidProtocolBufferException ex) {
-      throw new InvalidRequestException("Invalid version " + parameter.key(), 
operation, ex);
-    }
-    return CoreWaveletOperationSerializer.deserialize(protoVersion);
-  }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ExportSnapshotService.java
----------------------------------------------------------------------
diff --git 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ExportSnapshotService.java
 
b/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ExportSnapshotService.java
deleted file mode 100644
index a65d69e..0000000
--- 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ExportSnapshotService.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.operations;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.gson.Gson;
-
-import com.google.wave.api.ApiIdSerializer;
-import com.google.wave.api.InvalidRequestException;
-import com.google.wave.api.JsonRpcConstant.ParamsProperty;
-import com.google.wave.api.OperationRequest;
-import com.google.wave.api.impl.GsonFactory;
-
-import org.waveprotocol.box.common.comms.WaveClientRpc.WaveletSnapshot;
-import org.waveprotocol.box.server.frontend.CommittedWaveletSnapshot;
-import org.waveprotocol.box.server.robots.OperationContext;
-import org.waveprotocol.wave.model.id.InvalidIdException;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.util.logging.Log;
-import org.waveprotocol.wave.model.id.WaveId;
-import org.waveprotocol.wave.model.id.WaveletId;
-import org.waveprotocol.wave.model.id.WaveletName;
-import org.waveprotocol.box.server.robots.util.OperationUtil;
-import org.waveprotocol.box.server.common.SnapshotSerializer;
-import org.waveprotocol.box.common.comms.proto.WaveletSnapshotProtoImpl;
-
-import java.util.Map;
-
-/**
- * {@link OperationService} for the "exportSnapshot" operation.
- *
- * @author akapla...@gmail.com (Andrew Kaplanov)
- */
-public class ExportSnapshotService implements OperationService {
-  private static final Log LOG = Log.get(ExportSnapshotService.class);
-
-  private static final Gson gson = new GsonFactory().create();
-
-  private ExportSnapshotService() {
-  }
-
-  @Override
-  public void execute(OperationRequest operation, OperationContext context, 
ParticipantId participant)
-      throws InvalidRequestException {
-    WaveId waveId;
-    WaveletId waveletId;
-    try {
-      waveId = ApiIdSerializer.instance().deserialiseWaveId(
-        OperationUtil.<String>getRequiredParameter(operation, 
ParamsProperty.WAVE_ID));
-      waveletId = ApiIdSerializer.instance().deserialiseWaveletId(
-        OperationUtil.<String>getRequiredParameter(operation, 
ParamsProperty.WAVELET_ID));
-    } catch (InvalidIdException ex) {
-      throw new InvalidRequestException("Invalid id", operation, ex);
-    }
-    WaveletName waveletName = WaveletName.of(waveId, waveletId);
-    CommittedWaveletSnapshot snapshot = 
context.getWaveletSnapshot(waveletName, participant);
-    WaveletSnapshot protoSnapshot = 
SnapshotSerializer.serializeWavelet(snapshot.snapshot, 
snapshot.snapshot.getHashedVersion());
-    WaveletSnapshotProtoImpl protoSnapshotImpl = new 
WaveletSnapshotProtoImpl(protoSnapshot);
-    String jsonSnapshot = gson.toJson(protoSnapshotImpl.toGson(null, gson));
-    Map<ParamsProperty, Object> data =
-      ImmutableMap.<ParamsProperty, Object> of(ParamsProperty.RAW_SNAPSHOT, 
jsonSnapshot);
-    context.constructResponse(operation, data);
-  }
-
-  public static ExportSnapshotService create() {
-    return new ExportSnapshotService();
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/operations/FetchProfilesService.java
----------------------------------------------------------------------
diff --git 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/FetchProfilesService.java
 
b/wave/src/main/java/org/waveprotocol/box/server/robots/operations/FetchProfilesService.java
deleted file mode 100644
index 1079f98..0000000
--- 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/FetchProfilesService.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.operations;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import com.google.inject.Inject;
-import com.google.wave.api.FetchProfilesRequest;
-import com.google.wave.api.FetchProfilesResult;
-import com.google.wave.api.InvalidRequestException;
-import com.google.wave.api.JsonRpcConstant.ParamsProperty;
-import com.google.wave.api.OperationRequest;
-import com.google.wave.api.ParticipantProfile;
-
-import org.waveprotocol.box.server.robots.OperationContext;
-import org.waveprotocol.box.server.robots.util.OperationUtil;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * {@link OperationService} for the "fetchProfiles" operation.
- *
- * @author yur...@apache.org (Yuri Zelikov)
- */
-public class FetchProfilesService implements OperationService {
-
-  public interface ProfilesFetcher {
-
-    public static final String UNKNOWN_IMAGE = "/static/images/unknown.jpg";
-    public static final String UNKNOWN_PROFILE = "";
-
-    ParticipantProfile fetchProfile(String address);
-
-    /** A simple profiles fetcher implementation. */
-    static ProfilesFetcher SIMPLE_PROFILES_FETCHER = new ProfilesFetcher() {
-
-      /**
-       * Attempts to create the fragments of the participant's name from their
-       * address, for example "john.sm...@example.com" into ["John", "Smith"].
-       */
-      private String buildNames(String address) {
-        // TODO (user) This code replicates ProfileImpl and should be 
refactored
-        // so the two classes can share the code properly.
-        String fullName;
-        List<String> names = Lists.newArrayList();
-        String nameWithoutDomain = address.split("@")[0];
-        if (nameWithoutDomain != null && !nameWithoutDomain.isEmpty()) {
-          // Include empty names from fragment, so split with a -ve.
-          for (String fragment : nameWithoutDomain.split("[._]", -1)) {
-            if (!fragment.isEmpty()) {
-              names.add(capitalize(fragment));
-            }
-          }
-          // ParticipantId normalization implies names can not be empty.
-          assert !names.isEmpty();
-          fullName = Joiner.on(' ').join(names);
-          return fullName;
-        } else {
-          // Name can be empty in case of shared domain participant which has
-          // the the form: @example.com.
-          return address;
-        }
-      }
-
-      private String capitalize(String s) {
-        return s.isEmpty() ? s : (Character.toUpperCase(s.charAt(0))) + 
s.substring(1);
-      }
-
-      @Override
-      public ParticipantProfile fetchProfile(String address) {
-        String name = buildNames(address);
-        return new ParticipantProfile(address, name, UNKNOWN_IMAGE, 
UNKNOWN_PROFILE);
-      }
-    };
-  }
-
-  private final ProfilesFetcher profilesFetcher;
-
-  @Inject
-  public FetchProfilesService(ProfilesFetcher profilesFetcher) {
-    this.profilesFetcher = profilesFetcher;
-  }
-
-  @Override
-  public void execute(OperationRequest operation, OperationContext context,
-      ParticipantId participant) throws InvalidRequestException {
-    FetchProfilesRequest request =
-        OperationUtil.getRequiredParameter(operation, 
ParamsProperty.FETCH_PROFILES_REQUEST);
-    List<String> requestAddresses = request.getParticipantIds();
-    List<ParticipantProfile> profiles = 
Lists.newArrayListWithCapacity(requestAddresses.size());
-    for (String address : requestAddresses) {
-      ParticipantProfile participantProfile = 
profilesFetcher.fetchProfile(address);
-      profiles.add(participantProfile);
-    }
-    FetchProfilesResult result = new FetchProfilesResult(profiles);
-    Map<ParamsProperty, Object> data =
-        ImmutableMap.<ParamsProperty, Object> 
of(ParamsProperty.FETCH_PROFILES_RESULT, result);
-    context.constructResponse(operation, data);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/operations/FetchWaveService.java
----------------------------------------------------------------------
diff --git 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/FetchWaveService.java
 
b/wave/src/main/java/org/waveprotocol/box/server/robots/operations/FetchWaveService.java
deleted file mode 100644
index 48d8181..0000000
--- 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/FetchWaveService.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.operations;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-
-import com.google.wave.api.InvalidRequestException;
-import com.google.wave.api.JsonRpcConstant.ParamsProperty;
-import com.google.wave.api.OperationRequest;
-import com.google.wave.api.data.converter.ContextResolver;
-import com.google.wave.api.data.converter.EventDataConverter;
-import com.google.wave.api.event.WaveletFetchedEvent;
-import com.google.wave.api.impl.EventMessageBundle;
-import com.google.wave.api.impl.WaveletData;
-
-import org.waveprotocol.box.server.robots.OperationContext;
-import org.waveprotocol.box.server.robots.util.ConversationUtil;
-import org.waveprotocol.box.server.robots.util.OperationUtil;
-
-import org.waveprotocol.wave.model.conversation.Conversation;
-import org.waveprotocol.wave.model.conversation.ObservableConversation;
-import org.waveprotocol.wave.model.id.WaveletId;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.model.wave.Wavelet;
-import org.waveprotocol.wave.model.wave.opbased.OpBasedWavelet;
-
-import java.util.Map;
-
-/**
- * {@link OperationService} for the "fetchWave" operation.
- *
- * @author ljvder...@google.com (Lennard de Rijk)
- * @author akapla...@gmail.com (Andrew Kaplanov)
- */
-public class FetchWaveService implements OperationService {
-
-  private FetchWaveService() {
-  }
-
-  @Override
-  public void execute(OperationRequest operation, OperationContext context, 
ParticipantId participant)
-      throws InvalidRequestException {
-    if (OperationUtil.<Boolean>getOptionalParameter(operation, 
ParamsProperty.RETURN_WAVELET_IDS, false)) {
-      ImmutableSet<WaveletId> waveletIds = 
context.getVisibleWaveletIds(operation, participant);
-      Map<ParamsProperty, Object> data =
-          ImmutableMap.<ParamsProperty, Object>of(ParamsProperty.WAVELET_IDS, 
waveletIds);
-      context.constructResponse(operation, data);
-    } else {
-      OpBasedWavelet wavelet = context.openWavelet(operation, participant);
-      ObservableConversation conversation =
-          context.openConversation(operation, participant).getRoot();
-
-      EventMessageBundle messages =
-          mapWaveletToMessageBundle(context.getConverter(), participant, 
wavelet, conversation);
-
-      String rootBlipId = ConversationUtil.getRootBlipId(conversation);
-      String message = OperationUtil.getOptionalParameter(operation, 
ParamsProperty.MESSAGE);
-
-      WaveletFetchedEvent event =
-          new WaveletFetchedEvent(null, null, participant.getAddress(), 
System.currentTimeMillis(),
-          message, rootBlipId, messages.getWaveletData(), 
messages.getBlipData(),
-          messages.getThreads());
-
-      context.processEvent(operation, event);
-    }
-  }
-
-  /**
-   * Maps a wavelet and its conversation to a new {@link EventMessageBundle}.
-   *
-   * @param converter to convert to API objects.
-   * @param participant the participant who the bundle is for.
-   * @param wavelet the wavelet to put in the bundle.
-   * @param conversation the conversation to put in the bundle.
-   */
-  private EventMessageBundle mapWaveletToMessageBundle(EventDataConverter 
converter,
-      ParticipantId participant, Wavelet wavelet, Conversation conversation) {
-    EventMessageBundle messages = new 
EventMessageBundle(participant.getAddress(), "");
-    WaveletData waveletData = converter.toWaveletData(wavelet, conversation, 
messages);
-    messages.setWaveletData(waveletData);
-    ContextResolver.addAllBlipsToEventMessages(messages, conversation, 
wavelet, converter);
-    return messages;
-  }
-
-  public static FetchWaveService create() {
-    return new FetchWaveService();
-  }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/operations/FolderActionService.java
----------------------------------------------------------------------
diff --git 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/FolderActionService.java
 
b/wave/src/main/java/org/waveprotocol/box/server/robots/operations/FolderActionService.java
deleted file mode 100644
index 8f72a46..0000000
--- 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/FolderActionService.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.operations;
-
-import static 
org.waveprotocol.box.server.robots.util.OperationUtil.buildSupplement;
-
-import com.google.common.collect.Maps;
-import com.google.wave.api.InvalidRequestException;
-import com.google.wave.api.JsonRpcConstant.ParamsProperty;
-import com.google.wave.api.OperationRequest;
-
-import org.waveprotocol.box.server.robots.OperationContext;
-import org.waveprotocol.box.server.robots.util.OperationUtil;
-import org.waveprotocol.wave.model.conversation.ConversationBlip;
-import org.waveprotocol.wave.model.conversation.ObservableConversation;
-import org.waveprotocol.wave.model.supplement.SupplementedWave;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-
-import java.util.Map;
-
-/**
- * Implements the "robot.folderAction" operations.
- * 
- * @author yur...@apache.org (Yuri Zelikov)
- */
-public class FolderActionService implements OperationService {
-
-  public enum ModifyHowType {
-    MARK_AS_READ("markAsRead"), MARK_AS_UNREAD("markAsUnread");
-
-    private final String value;
-
-    private ModifyHowType(String value) {
-      this.value = value;
-    }
-
-    public String getValue() {
-      return value;
-    }
-  }
-
-  public static FolderActionService create() {
-    return new FolderActionService();
-  }
-
-  @Override
-  public void execute(OperationRequest operation, OperationContext context,
-      ParticipantId participant) throws InvalidRequestException {
-
-    String modifyHow = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.MODIFY_HOW);
-    String blipId = OperationUtil.getOptionalParameter(operation, 
ParamsProperty.BLIP_ID);
-
-    SupplementedWave supplement = buildSupplement(operation, context, 
participant);
-
-    if (modifyHow.equals(ModifyHowType.MARK_AS_READ.getValue())) {
-      if (blipId == null || blipId.isEmpty()) {
-        supplement.markAsRead();
-      } else {
-        ObservableConversation conversation =
-            context.openConversation(operation, participant).getRoot();
-        ConversationBlip blip = conversation.getBlip(blipId);
-        supplement.markAsRead(blip);
-      }
-    } else if (modifyHow.equals(ModifyHowType.MARK_AS_UNREAD.getValue())) {
-      supplement.markAsUnread();
-    } else {
-      throw new UnsupportedOperationException("Unsupported folder action: " + 
modifyHow);
-    }
-    // Construct empty response.
-    Map<ParamsProperty, Object> data = Maps.newHashMap();
-    context.constructResponse(operation, data);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/operations/GravatarProfilesFetcher.java
----------------------------------------------------------------------
diff --git 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/GravatarProfilesFetcher.java
 
b/wave/src/main/java/org/waveprotocol/box/server/robots/operations/GravatarProfilesFetcher.java
deleted file mode 100644
index c698e2d..0000000
--- 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/GravatarProfilesFetcher.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.operations;
-
-import com.google.inject.Inject;
-import com.google.wave.api.ParticipantProfile;
-import com.typesafe.config.Config;
-import org.apache.commons.codec.digest.DigestUtils;
-import 
org.waveprotocol.box.server.robots.operations.FetchProfilesService.ProfilesFetcher;
-
-/**
- * A {@link ProfilesFetcher} implementation that assigns a Gravatar identicon
- * image URL for the user avatar. Users can change the avatar image by going to
- * gravatar.com and adding their wave address to the main profile. It is
- * impossible to create a main profile with wave address since gravatar 
requires
- * email address verification.
-*
- * @author yur...@apache.org (Yuri Zelikov)
- */
-public class GravatarProfilesFetcher implements ProfilesFetcher {
-
-  private final static String SECURE_GRAVATAR_URL = 
"https://secure.gravatar.com/avatar/";;
-  private final static String NON_SECURE_GRAVATAR_URL = 
"http://gravatar.com/avatar/";;
-
-  private final String gravatarUrl;
-
-  @Inject
-  public GravatarProfilesFetcher(Config config) {
-    if (config.getBoolean("security.enable_ssl")) {
-      gravatarUrl = SECURE_GRAVATAR_URL;
-    } else {
-      gravatarUrl = NON_SECURE_GRAVATAR_URL;
-    }
-  }
-
-  /**
-   * Returns the Gravatar identicon URL for the given email address.
-   */
-  public String getImageUrl(String email) {
-    // Hexadecimal MD5 hash of the requested user's lowercased email address
-    // with all whitespace trimmed.
-    String emailHash = DigestUtils.md5Hex(email.toLowerCase().trim());
-    return gravatarUrl + emailHash + ".jpg?s=100&d=identicon";
-  }
-
-  @Override
-  public ParticipantProfile fetchProfile(String email) {
-    ParticipantProfile pTemp;
-    pTemp = ProfilesFetcher.SIMPLE_PROFILES_FETCHER.fetchProfile(email);
-    return new ParticipantProfile(email, pTemp.getName(), getImageUrl(email), 
pTemp.getProfileUrl());
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ImportAttachmentService.java
----------------------------------------------------------------------
diff --git 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ImportAttachmentService.java
 
b/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ImportAttachmentService.java
deleted file mode 100644
index 490b9f1..0000000
--- 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ImportAttachmentService.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.waveprotocol.box.server.robots.operations;
-
-import com.google.common.collect.Maps;
-import com.google.wave.api.InvalidRequestException;
-import com.google.wave.api.OperationRequest;
-import com.google.inject.Inject;
-import com.google.wave.api.ApiIdSerializer;
-import com.google.wave.api.JsonRpcConstant.ParamsProperty;
-import com.google.wave.api.impl.RawAttachmentData;
-
-import org.waveprotocol.box.server.robots.OperationContext;
-import org.waveprotocol.box.server.attachment.AttachmentService;
-import org.waveprotocol.box.server.robots.util.OperationUtil;
-import org.waveprotocol.wave.model.wave.InvalidParticipantAddress;
-import org.waveprotocol.wave.util.logging.Log;
-import org.waveprotocol.wave.media.model.AttachmentId;
-import org.waveprotocol.wave.model.id.*;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-
-import java.io.IOException;
-import java.io.ByteArrayInputStream;
-import java.util.Map;
-
-/**
- * {@link OperationService} for the "importAttachment" operation.
- * @author akapla...@gmail.com (Andrew Kaplanov)
- */
-public class ImportAttachmentService implements OperationService {
-  private static final Log LOG = Log.get(ImportAttachmentService.class);
-  private final AttachmentService attachmentService;
-
-  @Inject
-  public ImportAttachmentService(AttachmentService attachmentService) {
-    this.attachmentService = attachmentService;
-  }
-
-  @Override
-  public void execute(OperationRequest operation, OperationContext context, 
ParticipantId participant)
-      throws InvalidRequestException {
-    WaveId waveId;
-    WaveletId waveletId;
-    AttachmentId attachmentId;
-    RawAttachmentData attachmentData;
-    try {
-      waveId = ApiIdSerializer.instance().deserialiseWaveId(
-          OperationUtil.<String>getRequiredParameter(operation, 
ParamsProperty.WAVE_ID));
-      waveletId = ApiIdSerializer.instance().deserialiseWaveletId(
-          OperationUtil.<String>getRequiredParameter(operation, 
ParamsProperty.WAVELET_ID));
-      attachmentId =  
AttachmentId.deserialise(OperationUtil.<String>getRequiredParameter(operation,
-          ParamsProperty.ATTACHMENT_ID));
-      attachmentData = 
OperationUtil.<RawAttachmentData>getRequiredParameter(operation,
-          ParamsProperty.ATTACHMENT_DATA);
-    } catch (InvalidIdException ex) {
-      throw new InvalidRequestException("Invalid id", operation, ex);
-    }
-    try {
-      attachmentService.storeAttachment(attachmentId, new 
ByteArrayInputStream(attachmentData.getData()),
-        WaveletName.of(waveId, waveletId), attachmentData.getFileName(), 
ParticipantId.of(attachmentData.getCreator()));
-    } catch (InvalidParticipantAddress ex) {
-      throw new InvalidRequestException("Invalid participant " + 
attachmentData.getCreator(), operation, ex);
-    } catch (IOException ex) {
-      LOG.severe("Store attachment", ex);
-      context.constructErrorResponse(operation, ex.toString());
-      return;
-    }
-    Map<ParamsProperty, Object> response = Maps.<ParamsProperty, 
Object>newHashMap();
-    context.constructResponse(operation, response);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ImportDeltasService.java
----------------------------------------------------------------------
diff --git 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ImportDeltasService.java
 
b/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ImportDeltasService.java
deleted file mode 100644
index e9024c1..0000000
--- 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ImportDeltasService.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.waveprotocol.box.server.robots.operations;
-
-import com.google.common.collect.Maps;
-import com.google.wave.api.InvalidRequestException;
-import com.google.wave.api.OperationRequest;
-import com.google.inject.Inject;
-import com.google.inject.name.Named;
-import com.google.protobuf.ByteString;
-import com.google.protobuf.InvalidProtocolBufferException;
-import com.google.wave.api.ApiIdSerializer;
-import com.google.wave.api.JsonRpcConstant.ParamsProperty;
-
-import org.waveprotocol.box.server.CoreSettingsNames;
-import org.waveprotocol.box.server.robots.OperationContext;
-import org.waveprotocol.box.server.frontend.CommittedWaveletSnapshot;
-import org.waveprotocol.box.server.waveserver.WaveServerException;
-import org.waveprotocol.box.server.waveserver.WaveletProvider;
-import org.waveprotocol.box.server.robots.util.OperationUtil;
-import org.waveprotocol.wave.model.version.HashedVersion;
-import org.waveprotocol.wave.model.wave.InvalidParticipantAddress;
-import org.waveprotocol.wave.util.logging.Log;
-import org.waveprotocol.wave.federation.Proto.ProtocolHashedVersion;
-import org.waveprotocol.wave.federation.Proto.ProtocolWaveletDelta;
-import org.waveprotocol.wave.model.id.*;
-import org.waveprotocol.wave.model.version.HashedVersionFactory;
-import org.waveprotocol.wave.model.version.HashedVersionFactoryImpl;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.util.escapers.jvm.JavaUrlCodec;
-
-import java.util.Map;
-import java.util.List;
-
-/**
- * {@link OperationService} for the "importDeltas" operation.
- * @author akapla...@gmail.com (Andrew Kaplanov)
- */
-public class ImportDeltasService implements OperationService {
-  private static final Log LOG = Log.get(ImportDeltasService.class);
-  private static final IdURIEncoderDecoder URI_CODEC = new 
IdURIEncoderDecoder(new JavaUrlCodec());
-  private static final HashedVersionFactory HASH_FACTORY = new 
HashedVersionFactoryImpl(URI_CODEC);
-  private final WaveletProvider waveletProvider;
-  private final String waveDomain;
-
-  @Inject
-  public ImportDeltasService(WaveletProvider waveletProvider,
-      @Named(CoreSettingsNames.WAVE_SERVER_DOMAIN) final String waveDomain) {
-    this.waveletProvider = waveletProvider;
-    this.waveDomain = waveDomain;
-  }
-
-  @Override
-  public void execute(OperationRequest operation, OperationContext context, 
ParticipantId participant)
-      throws InvalidRequestException {
-    WaveId waveId;
-    WaveletId waveletId;
-    try {
-      waveId = ApiIdSerializer.instance().deserialiseWaveId(
-          OperationUtil.<String>getRequiredParameter(operation, 
ParamsProperty.WAVE_ID));
-      waveletId = ApiIdSerializer.instance().deserialiseWaveletId(
-          OperationUtil.<String>getRequiredParameter(operation, 
ParamsProperty.WAVELET_ID));
-    } catch (InvalidIdException ex) {
-      throw new InvalidRequestException("Invalid id", operation, ex);
-    }
-    waveId = WaveId.of(waveDomain, waveId.getId());
-    waveletId = WaveletId.of(waveDomain, waveletId.getId());
-    List<byte[]> history =
-        OperationUtil.getRequiredParameter(operation, 
ParamsProperty.RAW_DELTAS);
-    WaveletName waveletName = WaveletName.of(waveId, waveletId);
-    long importedFromVersion = -1;
-    if (!history.isEmpty()) {
-      CommittedWaveletSnapshot waveletSnapshot;
-      try {
-        waveletSnapshot = waveletProvider.getSnapshot(waveletName);
-      } catch (WaveServerException ex) {
-        LOG.info("Get wavelet snapshot", ex);
-        context.constructErrorResponse(operation, ex.toString());
-        return;
-      }
-      for (byte[] deltaBytes : history) {
-        ProtocolWaveletDelta delta;
-        try {
-          delta = ProtocolWaveletDelta.parseFrom(deltaBytes);
-        } catch (InvalidProtocolBufferException ex) {
-          throw new InvalidRequestException("Parse delta", operation, ex);
-        }
-        long currentVersion = 0;
-        if (waveletSnapshot != null) {
-          currentVersion = waveletSnapshot.snapshot.getVersion();
-        }
-        if (currentVersion == delta.getHashedVersion().getVersion()) {
-          if (importedFromVersion == -1) {
-            importedFromVersion = currentVersion;
-          }
-          ProtocolWaveletDelta newDelta;
-          try {
-            newDelta = setVersionHash(delta, waveletSnapshot, waveletName);
-          } catch (InvalidParticipantAddress ex) {
-            throw new InvalidRequestException("Convert delta", operation, ex);
-          }
-          final StringBuffer error = new StringBuffer();
-          waveletProvider.submitRequest(waveletName, newDelta,
-              new WaveletProvider.SubmitRequestListener() {
-
-                @Override
-                public void onSuccess(int operationsApplied, HashedVersion 
hashedVersionAfterApplication,
-                    long applicationTimestamp) {
-                }
-
-                @Override
-                public void onFailure(String errorMessage) {
-                  error.append(errorMessage);
-                }
-              });
-          if (error.length() != 0) {
-            context.constructErrorResponse(operation, error.toString());
-            return;
-          }
-          if (waveletSnapshot == null) {
-            try {
-              waveletSnapshot = waveletProvider.getSnapshot(waveletName);
-            } catch (WaveServerException ex) {
-              LOG.info("Get wavelet snapshot", ex);
-              context.constructErrorResponse(operation, ex.toString());
-              return;
-            }
-          }
-        } else if (importedFromVersion != -1) {
-          context.constructErrorResponse(operation, "Expected wavelet version "
-              + delta.getHashedVersion().getVersion() + ", but current version 
is " + currentVersion + "."
-              + "Possibly wavelet is modified during import.");
-          return;
-        }
-      }
-    }
-    Map<ParamsProperty, Object> response = Maps.<ParamsProperty, Object> 
newHashMap();
-    response.put(ParamsProperty.IMPORTED_FROM_VERSION, importedFromVersion);
-    context.constructResponse(operation, response);
-  }
-
-  /**
-   * Sets correct version hash to delta.
-   *
-   * @param delta the source delta.
-   * @param waveletSnapshot to append delta.
-   * @param waveletName name of wavelet.
-   * @return the delta to import.
-   * @throws InvalidParticipantAddress deserialize of participant error.
-   */
-  ProtocolWaveletDelta setVersionHash(ProtocolWaveletDelta delta,
-      CommittedWaveletSnapshot waveletSnapshot, WaveletName waveletName) 
throws InvalidParticipantAddress {
-    ProtocolWaveletDelta.Builder newDelta = 
ProtocolWaveletDelta.newBuilder(delta);
-    if (waveletSnapshot == null) {
-      ProtocolHashedVersion ver = 
ProtocolHashedVersion.newBuilder(delta.getHashedVersion()).
-          
setHistoryHash(ByteString.copyFrom(HASH_FACTORY.createVersionZero(waveletName).getHistoryHash())).
-          build();
-      newDelta.setHashedVersion(ver);
-    } else {
-      ProtocolHashedVersion ver = 
ProtocolHashedVersion.newBuilder(delta.getHashedVersion()).
-          
setHistoryHash(ByteString.copyFrom(waveletSnapshot.snapshot.getHashedVersion().getHistoryHash())).
-          build();
-      newDelta.setHashedVersion(ver);
-    }
-    return newDelta.build();
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/operations/InitialsProfilesFetcher.java
----------------------------------------------------------------------
diff --git 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/InitialsProfilesFetcher.java
 
b/wave/src/main/java/org/waveprotocol/box/server/robots/operations/InitialsProfilesFetcher.java
deleted file mode 100644
index e14b792..0000000
--- 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/InitialsProfilesFetcher.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.operations;
-
-import com.google.wave.api.ParticipantProfile;
-
-import 
org.waveprotocol.box.server.robots.operations.FetchProfilesService.ProfilesFetcher;
-
-/**
- * A {@link ProfilesFetcher} implementation that assigns a default image URL 
for
- * the user avatar using it's initial and a random color
- *
- * @author v...@apache.org (Vicente J. Ruiz Jurado)
- */
-public class InitialsProfilesFetcher implements ProfilesFetcher {
-
-  /**
-   * Returns the avatar URL for the given email address.
-   */
-  public String getImageUrl(String email) {
-    return "/iniavatars/100x100/" + email;
-  }
-
-  @Override
-  public ParticipantProfile fetchProfile(String email) {
-    ParticipantProfile pTemp = null;
-    pTemp = ProfilesFetcher.SIMPLE_PROFILES_FETCHER.fetchProfile(email);
-    ParticipantProfile profile =
-        new ParticipantProfile(email, pTemp.getName(), getImageUrl(email), 
pTemp.getProfileUrl());
-    return profile;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/operations/NotifyOperationService.java
----------------------------------------------------------------------
diff --git 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/NotifyOperationService.java
 
b/wave/src/main/java/org/waveprotocol/box/server/robots/operations/NotifyOperationService.java
deleted file mode 100644
index 6812e37..0000000
--- 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/NotifyOperationService.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.operations;
-
-import com.google.common.collect.Maps;
-import com.google.inject.Inject;
-import com.google.wave.api.InvalidRequestException;
-import com.google.wave.api.OperationRequest;
-import com.google.wave.api.JsonRpcConstant.ParamsProperty;
-import com.google.wave.api.robot.CapabilityFetchException;
-import com.google.wave.api.robot.RobotName;
-
-import org.waveprotocol.box.server.account.AccountData;
-import org.waveprotocol.box.server.account.RobotAccountData;
-import org.waveprotocol.box.server.persistence.AccountStore;
-import org.waveprotocol.box.server.persistence.PersistenceException;
-import org.waveprotocol.box.server.robots.OperationContext;
-import org.waveprotocol.box.server.robots.RobotCapabilities;
-import org.waveprotocol.box.server.robots.passive.RobotConnector;
-import org.waveprotocol.box.server.robots.util.OperationUtil;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.util.logging.Log;
-
-/**
- * Implementation of the robot.notify operation which might update the robot's
- * capabilties.
- * 
- * @author ljvder...@gmail.com (Lennard de Rijk)
- */
-public class NotifyOperationService implements OperationService {
-
-  private static final Log LOG = Log.get(NotifyOperationService.class);
-
-  private final AccountStore accountStore;
-  private final RobotConnector connector;
-
-  @Inject
-  public NotifyOperationService(AccountStore accountStore, RobotConnector 
connector) {
-    this.accountStore = accountStore;
-    this.connector = connector;
-  }
-
-  @Override
-  public void execute(OperationRequest operation, OperationContext context,
-      ParticipantId participant) throws InvalidRequestException {
-    String capabilitiesHash =
-        OperationUtil.getRequiredParameter(operation, 
ParamsProperty.CAPABILITIES_HASH);
-
-    RobotName robotName = RobotName.fromAddress(participant.getAddress());
-
-    ParticipantId robotAccountId = 
ParticipantId.ofUnsafe(robotName.toEmailAddress());
-    AccountData account;
-    try {
-      account = accountStore.getAccount(robotAccountId);
-    } catch (PersistenceException e) {
-      LOG.severe("Failed to retreive account data for " + robotAccountId, e);
-      context.constructErrorResponse(operation, "Unable to retrieve account 
data");
-      return;
-    }
-
-    if (account == null || !account.isRobot()) {
-      throw new InvalidRequestException("Can't exectute robot.notify for 
unknown robot "
-          + robotAccountId);
-    }
-
-    RobotAccountData robotAccountData = account.asRobot();
-    RobotCapabilities capabilities = robotAccountData.getCapabilities();
-    if (capabilities != null && 
capabilitiesHash.equals(capabilities.getCapabilitiesHash())) {
-      // No change in capabilities indicated
-      context.constructResponse(operation, Maps.<ParamsProperty, Object> 
newHashMap());
-      return;
-    }
-
-    try {
-      robotAccountData = connector.fetchCapabilities(robotAccountData, "");
-    } catch (CapabilityFetchException e) {
-      LOG.fine("Unable to retrieve capabilities for " + account.getId(), e);
-      context.constructErrorResponse(operation, "Unable to retrieve new 
capabilities");
-      return;
-    }
-
-    try {
-      accountStore.putAccount(robotAccountData);
-    } catch (PersistenceException e) {
-      LOG.severe("Failed to update account data for " + robotAccountId, e);
-      context.constructErrorResponse(operation, "Unable to update account 
data");
-      return;
-    }
-
-    // Set empty response to indicate success
-    context.constructResponse(operation, Maps.<ParamsProperty, Object> 
newHashMap());
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/operations/OperationService.java
----------------------------------------------------------------------
diff --git 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/OperationService.java
 
b/wave/src/main/java/org/waveprotocol/box/server/robots/operations/OperationService.java
deleted file mode 100644
index 95512e9..0000000
--- 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/OperationService.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.operations;
-
-import com.google.wave.api.InvalidRequestException;
-import com.google.wave.api.OperationRequest;
-
-import org.waveprotocol.box.server.robots.OperationContext;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-
-/**
- * Executor of robot operations.
- *
- * @author ljvder...@google.com (Lennard de Rijk)
- */
-public interface OperationService {
-
-  /**
-   * Tries to execute the operation in the given context.
-   *
-   * @param operation the operation to execute.
-   * @param context the context of the operation.
-   * @param participant the participant performing this operation.
-   * @throws InvalidRequestException if the operation fails to perform.
-   */
-  void execute(OperationRequest operation, OperationContext context, 
ParticipantId participant)
-      throws InvalidRequestException;
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ParticipantServices.java
----------------------------------------------------------------------
diff --git 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ParticipantServices.java
 
b/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ParticipantServices.java
deleted file mode 100644
index 962c58f..0000000
--- 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/ParticipantServices.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.operations;
-
-import com.google.common.collect.Lists;
-import com.google.wave.api.InvalidRequestException;
-import com.google.wave.api.JsonRpcConstant.ParamsProperty;
-import com.google.wave.api.OperationRequest;
-import com.google.wave.api.OperationType;
-import com.google.wave.api.event.Event;
-import com.google.wave.api.event.WaveletParticipantsChangedEvent;
-
-import org.waveprotocol.box.server.robots.OperationContext;
-import org.waveprotocol.box.server.robots.util.ConversationUtil;
-import org.waveprotocol.box.server.robots.util.OperationUtil;
-import org.waveprotocol.wave.model.conversation.ObservableConversation;
-import org.waveprotocol.wave.model.wave.InvalidParticipantAddress;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import org.waveprotocol.wave.util.logging.Log;
-
-import java.util.List;
-
-/**
- * {@link OperationService} for operations that add or remove a participant.
- *
- * <p>
- * These operations are:
- * <li>{@link OperationType#WAVELET_ADD_PARTICIPANT_NEWSYNTAX}</li>
- * <li>{@link OperationType#WAVELET_REMOVE_PARTICIPANT_NEWSYNTAX}</li>.
- *
- * @author anthony dot watkins at sesi dot com (Anthony Watkins)
- */
-public class ParticipantServices implements OperationService {
-
-  private static final Log LOG = Log.get(ParticipantServices.class);
-
-  private ParticipantServices() {
-  }
-
-  /**
-   * Adds or Removes a Participant on a Wavelet.
-   *
-   * @param operation the operation to execute.
-   * @param context the context of the operation.
-   * @param participant the participant performing this operation.
-   * @throws InvalidRequestException if the operation fails to perform.
-   */
-  @Override
-  public void execute(OperationRequest operation, OperationContext context,
-      ParticipantId participant) throws InvalidRequestException {
-
-    // Get the conversation wavelet. If participant performing operation is not
-    // a member of wavelet, InvalidRequestException is thrown by this method.
-    ObservableConversation conversation =
-        context.openConversation(operation, participant).getRoot();
-
-    // Get participant operation is being performed on.
-    String paramParticipant =
-        OperationUtil.getRequiredParameter(operation, 
ParamsProperty.PARTICIPANT_ID);
-
-    ParticipantId targetParticipant;
-    try {
-      targetParticipant = ParticipantId.of(paramParticipant);
-    } catch (InvalidParticipantAddress e) {
-      String message = "Target ParticipantId " + paramParticipant + " is not " 
+ "valid";
-      LOG.info(message);
-      throw new InvalidRequestException(message);
-    }
-
-    String rootBlipId = ConversationUtil.getRootBlipId(conversation);
-
-    // Create generic event (defined by operation type) that will be processed
-    // by the context.
-    Event event;
-
-    // Set up participant containers.
-    List<String> participantsAdded = Lists.newArrayList();
-    List<String> participantsRemoved = Lists.newArrayList();
-
-    OperationType type = OperationUtil.getOperationType(operation);
-    switch (type) {
-      case WAVELET_ADD_PARTICIPANT_NEWSYNTAX:
-        // Make sure targetParticipant is not already member.
-        if (conversation.getParticipantIds().contains(targetParticipant)) {
-          String message = targetParticipant.getAddress() + " is already a " + 
"member of wavelet";
-          LOG.info(message);
-          throw new InvalidRequestException(message, operation);
-        }
-
-        // Add participant to conversation and send event.
-        conversation.addParticipant(targetParticipant);
-        participantsAdded.add(targetParticipant.getAddress());
-        event =
-            new WaveletParticipantsChangedEvent(null, null, 
participant.getAddress(),
-                System.currentTimeMillis(), rootBlipId, participantsAdded, 
participantsRemoved);
-        break;
-      case WAVELET_REMOVE_PARTICIPANT_NEWSYNTAX:
-        // Make sure targetParticipant is already member.
-        if (!conversation.getParticipantIds().contains(targetParticipant)) {
-          // Not a member, throw invalid request.
-          String message = targetParticipant.getAddress() + " is not a " + 
"member of wavelet";
-          LOG.info(message);
-          throw new InvalidRequestException(message, operation);
-        }
-
-        // Remove participant and send event.
-        conversation.removeParticipant(targetParticipant);
-        participantsRemoved.add(targetParticipant.getAddress());
-
-        event =
-            new WaveletParticipantsChangedEvent(null, null, 
participant.getAddress(),
-                System.currentTimeMillis(), rootBlipId, participantsAdded, 
participantsRemoved);
-        break;
-      default:
-        throw new UnsupportedOperationException(
-            "This OperationService does not implement operation of type " + 
type.method());
-    }
-
-    // Process the participant event.
-    context.processEvent(operation, event);
-  }
-
-  public static ParticipantServices create() {
-    return new ParticipantServices();
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/051db092/wave/src/main/java/org/waveprotocol/box/server/robots/operations/SearchService.java
----------------------------------------------------------------------
diff --git 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/SearchService.java
 
b/wave/src/main/java/org/waveprotocol/box/server/robots/operations/SearchService.java
deleted file mode 100644
index e8eeedd..0000000
--- 
a/wave/src/main/java/org/waveprotocol/box/server/robots/operations/SearchService.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.waveprotocol.box.server.robots.operations;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.inject.Inject;
-import com.google.wave.api.InvalidRequestException;
-import com.google.wave.api.JsonRpcConstant.ParamsProperty;
-import com.google.wave.api.OperationRequest;
-import com.google.wave.api.SearchResult;
-import org.waveprotocol.box.server.robots.OperationContext;
-import org.waveprotocol.box.server.robots.util.OperationUtil;
-import org.waveprotocol.box.server.waveserver.SearchProvider;
-import org.waveprotocol.wave.model.wave.ParticipantId;
-import java.util.Map;
-
-/**
- * {@link OperationService} for the "search" operation.
- *
- * @author ljvder...@google.com (Lennard de Rijk)
- * @author jose...@gmail.com (Joseph Gentle)
- */
-public class SearchService implements OperationService {
-
-  /**
-   * The number of search results to return if not defined in the request.
-   * Defined in the spec.
-   */
-  private static final int DEFAULT_NUMBER_SEARCH_RESULTS = 10;
-
-  private final SearchProvider searchProvider;
-
-  @Inject
-  public SearchService(SearchProvider searchProvider) {
-    this.searchProvider = searchProvider;
-  }
-
-  @Override
-  public void execute(
-      OperationRequest operation, OperationContext context, ParticipantId 
participant)
-      throws InvalidRequestException {
-    String query = OperationUtil.getRequiredParameter(operation, 
ParamsProperty.QUERY);
-    int index = OperationUtil.getOptionalParameter(operation, 
ParamsProperty.INDEX, 0);
-    int numResults = OperationUtil.getOptionalParameter(
-        operation, ParamsProperty.NUM_RESULTS, DEFAULT_NUMBER_SEARCH_RESULTS);
-
-    SearchResult result = search(participant, query, index, numResults);
-
-    Map<ParamsProperty, Object> data =
-        ImmutableMap.<ParamsProperty, Object> 
of(ParamsProperty.SEARCH_RESULTS, result);
-    context.constructResponse(operation, data);
-  }
-
-  // Note that this search implementation is only of prototype quality.
-  private SearchResult search(
-      ParticipantId participant, String query, int startAt, int numResults) {
-    return searchProvider.search(participant, query, startAt, numResults);
-  }
-}

Reply via email to