// 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 +
//                 '}';
//     }
// }


import static java.util.UUID.randomUUID;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.calrissian.flowmix.api.Aggregator;
import org.calrissian.flowmix.core.model.event.AggregatedEvent;
import org.calrissian.flowmix.core.support.window.WindowItem;
import org.calrissian.mango.domain.Tuple;
import org.calrissian.mango.domain.event.BaseEvent;
import org.calrissian.mango.domain.event.Event;
import static java.lang.System.currentTimeMillis;
  }

  @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(sumField) != null)
        sum += ((Long)item.getEvent().get(sumField).getValue());
    }

    @Override
    public void evicted(WindowItem item) {

      if(item.getEvent().get(sumField) != null)
        sum -= ((Long)item.getEvent().get(sumField).getValue());
    }

    @Override
    public List<AggregatedEvent> aggregate() {
      Event event = new BaseEvent(randomUUID().toString(), currentTimeMillis());
      if(groupedValues != null && groupByFields != null) {
        for(Collection<Tuple> tuples : groupedValues.values())
          event.putAll(tuples);
      }

      event.put(new Tuple(outputField, sum));
// 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/api/aggregator/LongSumAggregator.java
import static java.util.UUID.randomUUID;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.calrissian.flowmix.api.Aggregator;
import org.calrissian.flowmix.core.model.event.AggregatedEvent;
import org.calrissian.flowmix.core.support.window.WindowItem;
import org.calrissian.mango.domain.Tuple;
import org.calrissian.mango.domain.event.BaseEvent;
import org.calrissian.mango.domain.event.Event;
import static java.lang.System.currentTimeMillis;

  }

  @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(sumField) != null)
        sum += ((Long)item.getEvent().get(sumField).getValue());
    }

    @Override
    public void evicted(WindowItem item) {

      if(item.getEvent().get(sumField) != null)
        sum -= ((Long)item.getEvent().get(sumField).getValue());
    }

    @Override
    public List<AggregatedEvent> aggregate() {
      Event event = new BaseEvent(randomUUID().toString(), currentTimeMillis());
      if(groupedValues != null && groupByFields != null) {
        for(Collection<Tuple> tuples : groupedValues.values())
          event.putAll(tuples);
      }

      event.put(new Tuple(outputField, sum));
      return Collections.singletonList(new AggregatedEvent(event));