@Override
  public BlipData toBlipData(
      ConversationBlip blip, Wavelet wavelet, EventMessageBundle eventMessageBundle) {
    ConversationBlip parentBlip = findBlipParent(blip);
    BlipData blipData = new BlipData();
    blipData.setCreator(blip.getAuthorId().getAddress());
    blipData.setContributors(idsToParticipantIdList(blip.getContributorIds()));
    blipData.setBlipId(blip.getId());
    blipData.setLastModifiedTime(blip.getLastModifiedTime());
    blipData.setVersion(blip.getLastModifiedVersion());
    blipData.setParentBlipId(parentBlip == null ? null : parentBlip.getId());
    blipData.setWaveId(ApiIdSerializer.instance().serialiseWaveId(wavelet.getWaveId()));
    blipData.setWaveletId(ApiIdSerializer.instance().serialiseWaveletId(wavelet.getId()));
    blipData.setChildBlipIds(toBlipIdList(findBlipChildren(blip)));

    ApiView apiView = new ApiView(blip.getContent(), wavelet);
    // Set content.
    blipData.setContent(apiView.apiContents());
    // Set Annotations.
    blipData.setAnnotations(extractAnnotations(blip.getContent(), apiView));
    // blip.getContent().rangedAnnotations(0, blip.getContent().size(), null),
    // Set Form Elements.
    blipData.setElements(ElementSerializer.serialize(blip.getContent(), wavelet));
    return blipData;
  }
 /**
  * Extracts the blip ids of the given list of blips.
  *
  * @param children the blips.
  * @return the blip ids of the blips.
  */
 private static List<String> toBlipIdList(List<ConversationBlip> children) {
   List<String> ids = Lists.newArrayListWithCapacity(children.size());
   for (ConversationBlip child : children) {
     ids.add(child.getId());
   }
   return ids;
 }
 /**
  * Finds the parent of a blip. The parent is the preceding blip in the thread, or the blip to
  * which the thread is a reply for the first blip in a thread. The first blip of the root thread
  * has no parent.
  *
  * @param blip the blip.
  * @return the blip's parent, or {@code null} if the blip is the first blip in a conversation.
  */
 @Override
 public ConversationBlip findBlipParent(ConversationBlip blip) {
   ConversationThread containingThread = blip.getThread();
   if (containingThread.getFirstBlip() == blip
       && containingThread != blip.getConversation().getRootThread()) {
     return containingThread.getParentBlip();
   }
   return findPreviousSibling(blip);
 }
 /**
  * Retrieves the title of a {@link Wavelet}.
  *
  * @param wavelet The {@link Wavelet} to retrieve the title from.
  * @param conversation The wavelet conversation
  * @return the title of the {@link Wavelet}, or an empty string if it has no title.
  */
 private static String getTitle(Wavelet wavelet, Conversation conversation) {
   ConversationThread rootThread = conversation.getRootThread();
   if (rootThread == null) {
     return "";
   }
   ConversationBlip firstBlip = rootThread.getFirstBlip();
   if (firstBlip == null) {
     return "";
   }
   Document doc = firstBlip.getContent();
   return TitleHelper.extractTitle(doc);
 }
 /**
  * Finds the next sibling of a blip in a thread. The last blip in a thread has no next sibling.
  *
  * @param blip the blip.
  * @return the next sibling of the blip, or {@code null} if blip is the last blip in a thread.
  */
 @VisibleForTesting
 static ConversationBlip findNextSibling(ConversationBlip blip) {
   ConversationThread thread = blip.getThread();
   Iterator<? extends ConversationBlip> blips = thread.getBlips().iterator();
   boolean foundBlip = false;
   while (!foundBlip && blips.hasNext()) {
     if (blips.next() == blip) {
       foundBlip = true;
     }
   }
   return blips.hasNext() ? blips.next() : null;
 }
 /**
  * Finds the previous sibling of a blip in a thread. The first blip in a thread has no previous
  * sibling.
  *
  * @param blip the blip.
  * @return the previous sibling of the blip, or {@code null}.
  */
 @VisibleForTesting
 static ConversationBlip findPreviousSibling(ConversationBlip blip) {
   ConversationThread thread = blip.getThread();
   ConversationBlip previous = null;
   for (ConversationBlip sibling : thread.getBlips()) {
     if (sibling == blip) {
       break;
     }
     previous = sibling;
   }
   return previous;
 }
 /**
  * Finds the children of a blip, defined as the next sibling blip and the first blip in each reply
  * thread.
  *
  * @param blip the blip.
  * @return the children of the given blip.
  */
 @Override
 public List<ConversationBlip> findBlipChildren(ConversationBlip blip) {
   List<ConversationBlip> siblings = Lists.newArrayList();
   ConversationBlip nextSibling = findNextSibling(blip);
   if (nextSibling != null) {
     siblings.add(nextSibling);
   }
   for (ConversationThread reply : blip.getReplyThreads()) {
     if (reply.getFirstBlip() != null) {
       siblings.add(reply.getFirstBlip());
     }
   }
   return siblings;
 }