/**
   * The main processing method that will be called upon event arrival
   *
   * @param streamEventChunk the stream event chunk that need to be processed
   * @param nextProcessor the next processor to which the success events need to be passed
   * @param streamEventCloner helps to clone the incoming event for local storage or modification
   */
  @Override
  protected void process(
      ComplexEventChunk<StreamEvent> streamEventChunk,
      Processor nextProcessor,
      StreamEventCloner streamEventCloner) {
    synchronized (this) {
      long currentTime = executionPlanContext.getTimestampGenerator().currentTime();

      StreamEvent streamEvent = streamEventChunk.getFirst();
      streamEventChunk.clear();
      while (streamEvent != null) {
        StreamEvent clonedEvent = streamEventCloner.copyStreamEvent(streamEvent);
        clonedEvent.setType(StreamEvent.Type.EXPIRED);

        StreamEvent oldEvent = map.put(generateKey(clonedEvent), clonedEvent);
        if (oldEvent != null) {
          oldEvent.setTimestamp(currentTime);
          streamEventChunk.add(oldEvent);
        }
        StreamEvent next = streamEvent.getNext();
        streamEvent.setNext(null);
        streamEventChunk.add(streamEvent);
        streamEvent = next;
      }
    }
    nextProcessor.process(streamEventChunk);
  }
  @Override
  protected void process(
      ComplexEventChunk<StreamEvent> streamEventChunk,
      Processor nextProcessor,
      StreamEventCloner streamEventCloner,
      ComplexEventPopulater complexEventPopulater) {
    synchronized (this) {
      while (streamEventChunk.hasNext()) {
        StreamEvent streamEvent = streamEventChunk.next();
        if (logger.isDebugEnabled()) {
          logger.debug(
              String.format(
                  "Event received. Regex:%s Event:%s", regexPattern.pattern(), streamEvent));
        }

        Annotation document =
            pipeline.process(attributeExpressionExecutors[1].execute(streamEvent).toString());

        for (CoreMap sentence : document.get(CoreAnnotations.SentencesAnnotation.class)) {
          TokenSequenceMatcher matcher =
              regexPattern.getMatcher(sentence.get(CoreAnnotations.TokensAnnotation.class));
          while (matcher.find()) {
            Object[] data = new Object[attributeCount];
            data[0] = matcher.group();
            for (int i = 1; i < attributeCount; i++) {
              data[i] = matcher.group(i);
            }
            StreamEvent newStreamEvent = streamEventCloner.copyStreamEvent(streamEvent);
            complexEventPopulater.populateComplexEvent(newStreamEvent, data);
            streamEventChunk.insertBeforeCurrent(newStreamEvent);
          }
        }
        streamEventChunk.remove();
      }
    }
    nextProcessor.process(streamEventChunk);
  }