@Override
    public Boolean apply(PortalEvent event) {
      if (shutdown) {
        // Mark ourselves as interupted and throw an exception
        Thread.currentThread().interrupt();
        throw new RuntimeException(
            "uPortal is shutting down, throwing an exeption to stop aggregation");
      }

      final DateTime eventDate = event.getTimestampAsDate();
      this.lastEventDate.setValue(eventDate);

      // If no interval data yet populate it.
      if (this.currentIntervalInfo.isEmpty()) {
        initializeIntervalInfo(eventDate);
      }

      // Check each interval to see if an interval boundary has been crossed
      boolean intervalCrossed = false;
      for (final AggregationInterval interval :
          this.intervalsForAggregatorHelper.getHandledIntervals()) {
        AggregationIntervalInfo intervalInfo = this.currentIntervalInfo.get(interval);
        if (intervalInfo != null
            && !intervalInfo
                .getEnd()
                .isAfter(
                    eventDate)) { // if there is no IntervalInfo that interval must not be supported
                                  // in the current environment
          logger.debug("Crossing {} Interval, triggered by {}", interval, event);
          this.doHandleIntervalBoundary(interval, this.currentIntervalInfo);

          intervalInfo = intervalHelper.getIntervalInfo(interval, eventDate);
          this.currentIntervalInfo.put(interval, intervalInfo);

          this.aggregatorReadOnlyIntervalInfo
              .clear(); // Clear out cached per-aggregator interval info whenever a current interval
                        // info changes

          intervalCrossed = true;
        }
      }
      if (intervalCrossed) {
        this.intervalsCrossed++;

        // If we have crossed more intervals than the interval batch size return false to stop
        // aggregation before handling the triggering event
        if (this.intervalsCrossed >= intervalAggregationBatchSize) {
          return false;
        }
      }

      // Aggregate the event
      this.doAggregateEvent(event);

      // Update the status object with the event date
      this.lastEventDate.setValue(eventDate);

      // Continue processing
      return true;
    }
    protected EventSession getEventSession(PortalEvent item) {
      final String eventSessionId = item.getEventSessionId();

      // First check the aggregation context for a cached session event, fall back
      // to asking the DAO if nothing in the context, cache the result
      final CacheKey key = CacheKey.build(EVENT_SESSION_CACHE_KEY_SOURCE, eventSessionId);
      EventSession eventSession = this.eventAggregationContext.getAttribute(key);
      if (eventSession == null) {
        eventSession = eventSessionDao.getEventSession(item);
        this.eventAggregationContext.setAttribute(key, eventSession);
      }

      // Record the session access
      eventSession.recordAccess(item.getTimestampAsDate());
      eventSessionDao.storeEventSession(eventSession);

      return eventSession;
    }