// Path: src/main/java/org/calrissian/flowmix/api/Aggregator.java
// public interface Aggregator extends Serializable {
// 
//     public static final String GROUP_BY = "groupBy";
//     public static final String GROUP_BY_DELIM = "\u0000";
// 
//     void configure(Map<String, String> configuration);
// 
//     void added(WindowItem item);
// 
//     void evicted(WindowItem item);
// 
//     List<AggregatedEvent> aggregate();
// }
// 
// Path: src/main/java/org/calrissian/flowmix/core/model/event/AggregatedEvent.java
// public class AggregatedEvent {
// 
//   private Event event;
//   private String previousStream;
// 
//   public AggregatedEvent(Event event, String previousStream) {
//     this.event = event;
//     this.previousStream = previousStream;
//   }
// 
//   public AggregatedEvent(Event event) {
//     this.event = event;
//   }
// 
//   public Event getEvent() {
//     return event;
//   }
// 
//   public String getPreviousStream() {
//     return previousStream;
//   }
// 
//   @Override
//   public boolean equals(Object o) {
//     if (this == o) return true;
//     if (o == null || getClass() != o.getClass()) return false;
// 
//     AggregatedEvent that = (AggregatedEvent) o;
// 
//     if (event != null ? !event.equals(that.event) : that.event != null) return false;
//     if (previousStream != null ? !previousStream.equals(that.previousStream) : that.previousStream != null)
//       return false;
// 
//     return true;
//   }
// 
//   @Override
//   public int hashCode() {
//     int result = event != null ? event.hashCode() : 0;
//     result = 31 * result + (previousStream != null ? previousStream.hashCode() : 0);
//     return result;
//   }
// 
//   @Override
//   public String toString() {
//     return "AggregatedEvent{" +
//             "event=" + event +
//             ", previousStream='" + previousStream + '\'' +
//             '}';
//   }
// }
// 
// Path: src/main/java/org/calrissian/flowmix/core/support/window/WindowItem.java
// public class WindowItem {
//     Event event;
//     long timestamp;
//     String previousStream;
// 
//     public WindowItem(Event event, long timestamp, String previousStream) {
//         this.event = event;
//         this.timestamp = timestamp;
//         this.previousStream = previousStream;
//     }
// 
//     public Event getEvent() {
//         return event;
//     }
// 
//     public long getTimestamp() {
//         return timestamp;
//     }
// 
//     public String getPreviousStream() {
//       return previousStream;
//     }
// 
//     @Override
//     public String toString() {
//         return "WindowItem{" +
//                 "event=" + event +
//                 ", timestamp=" + timestamp +
//                 '}';
//     }
// }
// 
// Path: src/main/java/org/calrissian/flowmix/exceptions/FlowmixException.java
// public class FlowmixException extends RuntimeException {
// 
//     public FlowmixException(String msg, Throwable t) {
//         super(msg, t);
//     }
// 
// }


import org.calrissian.mango.domain.event.BaseEvent;
import org.calrissian.mango.domain.event.Event;
import static java.lang.System.currentTimeMillis;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static java.util.UUID.randomUUID;
import org.apache.commons.lang.StringUtils;
import org.calrissian.flowmix.api.Aggregator;
import static org.calrissian.flowmix.api.Aggregator.GROUP_BY;
import static org.calrissian.flowmix.api.Aggregator.GROUP_BY_DELIM;
import org.calrissian.flowmix.core.model.event.AggregatedEvent;
import org.calrissian.flowmix.core.support.window.WindowItem;
import org.calrissian.flowmix.exceptions.FlowmixException;
import org.calrissian.mango.domain.Tuple;
            operatedField = configuration.get(OPERATED_FIELD);
        } else {
            throw new RuntimeException("Aggregator needs a field to operate it. Property missing: " + OPERATED_FIELD);
        }
    }

    /**
     *
     * @param fieldValue field value to work with after item is added to grouped
     * values
     */
    public abstract void add(F fieldValue);

    /**
     *
     * @param item
     * @throws org.calrissian.flowmix.exceptions.FlowmixException
     */
    @Override
    public void added(WindowItem item){
        if (groupedValues == null && groupByFields != null) {
            groupedValues = new HashMap<String, Collection<Tuple>>();
            for (String group : groupByFields) {
                groupedValues.put(group, item.getEvent().getAll(group));
            }
        }
        if (item.getEvent().get(operatedField) != null) {
            try {
                add(((F) item.getEvent().get(operatedField).getValue()));
            } catch (ClassCastException e) {
// Path: src/main/java/org/calrissian/flowmix/api/Aggregator.java
// public interface Aggregator extends Serializable {
// 
//     public static final String GROUP_BY = "groupBy";
//     public static final String GROUP_BY_DELIM = "\u0000";
// 
//     void configure(Map<String, String> configuration);
// 
//     void added(WindowItem item);
// 
//     void evicted(WindowItem item);
// 
//     List<AggregatedEvent> aggregate();
// }
// 
// Path: src/main/java/org/calrissian/flowmix/core/model/event/AggregatedEvent.java
// public class AggregatedEvent {
// 
//   private Event event;
//   private String previousStream;
// 
//   public AggregatedEvent(Event event, String previousStream) {
//     this.event = event;
//     this.previousStream = previousStream;
//   }
// 
//   public AggregatedEvent(Event event) {
//     this.event = event;
//   }
// 
//   public Event getEvent() {
//     return event;
//   }
// 
//   public String getPreviousStream() {
//     return previousStream;
//   }
// 
//   @Override
//   public boolean equals(Object o) {
//     if (this == o) return true;
//     if (o == null || getClass() != o.getClass()) return false;
// 
//     AggregatedEvent that = (AggregatedEvent) o;
// 
//     if (event != null ? !event.equals(that.event) : that.event != null) return false;
//     if (previousStream != null ? !previousStream.equals(that.previousStream) : that.previousStream != null)
//       return false;
// 
//     return true;
//   }
// 
//   @Override
//   public int hashCode() {
//     int result = event != null ? event.hashCode() : 0;
//     result = 31 * result + (previousStream != null ? previousStream.hashCode() : 0);
//     return result;
//   }
// 
//   @Override
//   public String toString() {
//     return "AggregatedEvent{" +
//             "event=" + event +
//             ", previousStream='" + previousStream + '\'' +
//             '}';
//   }
// }
// 
// Path: src/main/java/org/calrissian/flowmix/core/support/window/WindowItem.java
// public class WindowItem {
//     Event event;
//     long timestamp;
//     String previousStream;
// 
//     public WindowItem(Event event, long timestamp, String previousStream) {
//         this.event = event;
//         this.timestamp = timestamp;
//         this.previousStream = previousStream;
//     }
// 
//     public Event getEvent() {
//         return event;
//     }
// 
//     public long getTimestamp() {
//         return timestamp;
//     }
// 
//     public String getPreviousStream() {
//       return previousStream;
//     }
// 
//     @Override
//     public String toString() {
//         return "WindowItem{" +
//                 "event=" + event +
//                 ", timestamp=" + timestamp +
//                 '}';
//     }
// }
// 
// Path: src/main/java/org/calrissian/flowmix/exceptions/FlowmixException.java
// public class FlowmixException extends RuntimeException {
// 
//     public FlowmixException(String msg, Throwable t) {
//         super(msg, t);
//     }
// 
// }


// Path: src/main/java/org/calrissian/flowmix/api/aggregator/AbstractAggregator.java
import org.calrissian.mango.domain.event.BaseEvent;
import org.calrissian.mango.domain.event.Event;
import static java.lang.System.currentTimeMillis;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static java.util.UUID.randomUUID;
import org.apache.commons.lang.StringUtils;
import org.calrissian.flowmix.api.Aggregator;
import static org.calrissian.flowmix.api.Aggregator.GROUP_BY;
import static org.calrissian.flowmix.api.Aggregator.GROUP_BY_DELIM;
import org.calrissian.flowmix.core.model.event.AggregatedEvent;
import org.calrissian.flowmix.core.support.window.WindowItem;
import org.calrissian.flowmix.exceptions.FlowmixException;
import org.calrissian.mango.domain.Tuple;

            operatedField = configuration.get(OPERATED_FIELD);
        } else {
            throw new RuntimeException("Aggregator needs a field to operate it. Property missing: " + OPERATED_FIELD);
        }
    }

    /**
     *
     * @param fieldValue field value to work with after item is added to grouped
     * values
     */
    public abstract void add(F fieldValue);

    /**
     *
     * @param item
     * @throws org.calrissian.flowmix.exceptions.FlowmixException
     */
    @Override
    public void added(WindowItem item){
        if (groupedValues == null && groupByFields != null) {
            groupedValues = new HashMap<String, Collection<Tuple>>();
            for (String group : groupByFields) {
                groupedValues.put(group, item.getEvent().getAll(group));
            }
        }
        if (item.getEvent().get(operatedField) != null) {
            try {
                add(((F) item.getEvent().get(operatedField).getValue()));
            } catch (ClassCastException e) {
                throw new FlowmixException("Problem converting value " + item.getEvent().get(operatedField).getValue(), e);