/**
   * This method processed an arrived real element The method is synchronized to ensure that it
   * cannot interleave with {@link StreamDiscretizer#triggerOnFakeElement(Object)}
   *
   * @param input a real input element
   * @throws Exception
   */
  protected synchronized void processRealElement(IN input) throws Exception {

    // Setting the input element in order to avoid NullFieldException when triggering on fake
    // element
    windowEvent.setElement(input);
    if (isActiveTrigger) {
      ActiveTriggerPolicy<IN> trigger = (ActiveTriggerPolicy<IN>) triggerPolicy;
      Object[] result = trigger.preNotifyTrigger(input);
      for (Object in : result) {
        triggerOnFakeElement(in);
      }
    }

    boolean isTriggered = false;

    if (triggerPolicy.notifyTrigger(input)) {
      emitWindow();
      isTriggered = true;
    }

    evict(input, isTriggered);

    output.collect(windowEvent.setElement(input));
    bufferSize++;
  }
 @Override
 public String toString() {
   return "Discretizer(Trigger: "
       + triggerPolicy.toString()
       + ", Eviction: "
       + evictionPolicy.toString()
       + ")";
 }
  @Override
  public boolean equals(Object other) {
    if (other == null
        || !(other instanceof StreamDiscretizer)
        || (other instanceof GroupedStreamDiscretizer)) {
      return false;
    } else {
      try {
        @SuppressWarnings("unchecked")
        StreamDiscretizer<IN> otherDiscretizer = (StreamDiscretizer<IN>) other;

        return triggerPolicy.equals(otherDiscretizer.triggerPolicy)
            && evictionPolicy.equals(otherDiscretizer.evictionPolicy);

      } catch (ClassCastException e) {
        return false;
      }
    }
  }