@Override
  public List<WatchListEvent> getEventsSince(Date start) {
    List<WatchListEvent> events = new ArrayList<>();

    XWikiContext context = getXWikiContext();

    ActivityStream actStream =
        ((ActivityStreamPlugin)
                context.getWiki().getPlugin(ActivityStreamPlugin.PLUGIN_NAME, context))
            .getActivityStream();
    List<Object> parameters = new ArrayList<Object>();
    parameters.add(start);

    try {
      // FIXME: Watch out for memory usage here, since the list of events could be huge in some
      // cases.
      List<ActivityEvent> rawEvents =
          actStream.searchEvents(
              "act.date > ? and act.type in ('"
                  + StringUtils.join(MATCHING_EVENT_TYPES, "','")
                  + "')",
              false,
              true,
              0,
              0,
              parameters,
              context);

      // If the page has been modified several times we want to display only one diff, if the page
      // has been
      // delete after update events we want to discard the update events since we won't be able to
      // display
      // diff from a deleted document. See WatchListEvent#addEvent(WatchListEvent) and
      // WatchListEvent#equals(WatchListEvent).
      for (ActivityEvent rawEvent : rawEvents) {
        WatchListEvent event = this.eventConverter.convert(rawEvent);

        int existingIndex = events.indexOf(event);
        if (existingIndex == -1) {
          // An event on a new document, add the new event.
          events.add(event);
        } else {
          // An event on an existing document, add to the events of that document.
          WatchListEvent existingCompositeEvent = events.get(existingIndex);
          existingCompositeEvent.addEvent(event);
        }
      }
    } catch (Exception e) {
      logger.error(
          "Failed to retrieve updated documents from activity stream since [{}]", start, e);
    }

    return events;
  }
 @Override
 public boolean isEventSkipped(WatchListEvent event) {
   // We exclude watchlist jobs from notifications since they are modified each time they are
   // fired,
   // producing useless noise.
   Collection<String> possibleIntervals = store.getIntervals();
   return possibleIntervals.contains(event.getFullName());
 }
  @Override
  public boolean isEventMatching(WatchListEvent event, String subscriber) {
    boolean isWatched = false;

    try {
      // The subscriber's watched users, since each event can be a composite event.
      Collection<String> watchedUsers =
          store.getWatchedElements(subscriber, WatchedElementType.USER);

      isWatched |= store.isWatched(event.getWiki(), subscriber, WatchedElementType.WIKI);
      isWatched |= store.isWatched(event.getPrefixedSpace(), subscriber, WatchedElementType.SPACE);
      isWatched |=
          store.isWatched(event.getPrefixedFullName(), subscriber, WatchedElementType.DOCUMENT);
      isWatched |= CollectionUtils.intersection(watchedUsers, event.getAuthors()).size() > 0;
    } catch (Exception e) {
      logger.error(
          "Failed to determine if an event for the document [{}] is interesting to [{}]",
          event.getDocumentReference(),
          subscriber,
          e);
    }

    return isWatched;
  }
 @Override
 public boolean isEventViewable(WatchListEvent event, String subscriber) {
   DocumentReference userReference = resolver.resolve(subscriber);
   return authorizationManager.hasAccess(Right.VIEW, userReference, event.getDocumentReference());
 }