/**
   * Invoked by the Aggregate objects that are timed out, to signal timeout/completion of itself
   *
   * @param aggregate the timed out Aggregate that holds collected messages and properties
   */
  public boolean completeAggregate(Aggregate aggregate) {

    boolean markedCompletedNow = false;
    boolean wasComplete = aggregate.isCompleted();
    if (wasComplete) {
      return false;
    }

    if (log.isDebugEnabled()) {
      log.debug("Aggregation completed or timed out");
    }

    // cancel the timer
    synchronized (this) {
      if (!aggregate.isCompleted()) {
        aggregate.cancel();
        aggregate.setCompleted(true);
        markedCompletedNow = true;
      }
    }

    if (!markedCompletedNow) {
      return false;
    }

    MessageContext newSynCtx = getAggregatedMessage(aggregate);

    if (newSynCtx == null) {
      log.warn("An aggregation of messages timed out with no aggregated messages", null);
      return false;
    } else {
      // Get the aggregated message to the next mediator placed after the aggregate mediator
      // in the sequence
      if (newSynCtx.isContinuationEnabled()) {
        try {
          aggregate
              .getLastMessage()
              .setEnvelope(MessageHelper.cloneSOAPEnvelope(newSynCtx.getEnvelope()));
        } catch (AxisFault axisFault) {
          log.warn(
              "Error occurred while assigning aggregated message"
                  + " back to the last received message context");
        }
      }
    }

    aggregate.clear();
    activeAggregates.remove(aggregate.getCorrelation());

    if ((correlateExpression != null
            && !correlateExpression.toString().equals(aggregate.getCorrelation()))
        || correlateExpression == null) {

      if (onCompleteSequence != null) {

        ContinuationStackManager.addReliantContinuationState(newSynCtx, 0, getMediatorPosition());
        boolean result = onCompleteSequence.mediate(newSynCtx);
        if (result) {
          ContinuationStackManager.removeReliantContinuationState(newSynCtx);
        }
        return result;

      } else if (onCompleteSequenceRef != null
          && newSynCtx.getSequence(onCompleteSequenceRef) != null) {

        ContinuationStackManager.updateSeqContinuationState(newSynCtx, getMediatorPosition());
        return newSynCtx.getSequence(onCompleteSequenceRef).mediate(newSynCtx);

      } else {
        handleException(
            "Unable to find the sequence for the mediation " + "of the aggregated message",
            newSynCtx);
      }
    }
    return false;
  }