// Path: myeslib-core/src/main/java/org/myeslib/core/data/Snapshot.java
// @SuppressWarnings("serial")
// @Value
// public class Snapshot<A extends AggregateRoot> implements Serializable {
// 	
// 	private A aggregateInstance;
// 	private Long version;
// 
// }
// 
// Path: myeslib-core/src/main/java/org/myeslib/core/storage/SnapshotReader.java
// public interface SnapshotReader<K, A extends AggregateRoot> {
// 	
// 	public Snapshot<A> get(final K id) ;
// 
// }
// 
// Path: inventory-aggregate-root/src/main/java/org/myeslib/example/SampleDomain.java
// @Data
// public static class InventoryItemAggregateRoot implements AggregateRoot {
// 
//     UUID id;
//     String description;
//     Integer available = 0;
// 
//     public void on(InventoryItemCreated event) {
//         this.id = event.id;
//         this.description = event.description;
//         this.available = 0;
//     }
// 
//     public void on(InventoryIncreased event) {
//         this.available = this.available + event.howMany;
//     }
// 
//     public void on(InventoryDecreased event) {
//         this.available = this.available - event.howMany;
//     }
//         
//     public boolean isAvailable(int howMany) {
//         return getAvailable() - howMany >= 0;
//     }
// 
// }


import java.util.List;
import java.util.UUID;
import java.util.Vector;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
import org.myeslib.core.data.Snapshot;
import org.myeslib.core.storage.SnapshotReader;
import org.myeslib.example.SampleDomain.InventoryItemAggregateRoot;
import com.google.inject.Inject;
import com.hazelcast.core.IMap;
import com.hazelcast.core.IQueue;
         .parallelProcessing()
         .streaming()
        //.log("received ${body}")
        .process(new Processor() {
            @Override
            public void process(Exchange e) throws Exception {
                UUID id = e.getIn().getBody(UUID.class);
                Snapshot<InventoryItemAggregateRoot> snapshot = snapshotReader.get(id);
                e.getOut().setHeader(ID, id);
                e.getOut().setBody(snapshot);
            }
        })
        //.log("produced ${body}")
		.to("direct:reflect-last-snapshot", "direct:reflect-query-model")
 		;
      
      from("direct:reflect-last-snapshot")
         .routeId("direct:reflect-last-snapshot")
         .process(new Processor() {
            @SuppressWarnings("unchecked")
            @Override
             public void process(Exchange e) throws Exception {
                 lastSnapshotMap.set(header(ID).evaluate(e, UUID.class), body().evaluate(e, Snapshot.class));
             }
         })
 	    ;

      from("direct:reflect-query-model")
      	.routeId("direct:reflect-query-model")
        .process(new Processor() {
// Path: myeslib-core/src/main/java/org/myeslib/core/data/Snapshot.java
// @SuppressWarnings("serial")
// @Value
// public class Snapshot<A extends AggregateRoot> implements Serializable {
// 	
// 	private A aggregateInstance;
// 	private Long version;
// 
// }
// 
// Path: myeslib-core/src/main/java/org/myeslib/core/storage/SnapshotReader.java
// public interface SnapshotReader<K, A extends AggregateRoot> {
// 	
// 	public Snapshot<A> get(final K id) ;
// 
// }
// 
// Path: inventory-aggregate-root/src/main/java/org/myeslib/example/SampleDomain.java
// @Data
// public static class InventoryItemAggregateRoot implements AggregateRoot {
// 
//     UUID id;
//     String description;
//     Integer available = 0;
// 
//     public void on(InventoryItemCreated event) {
//         this.id = event.id;
//         this.description = event.description;
//         this.available = 0;
//     }
// 
//     public void on(InventoryIncreased event) {
//         this.available = this.available + event.howMany;
//     }
// 
//     public void on(InventoryDecreased event) {
//         this.available = this.available - event.howMany;
//     }
//         
//     public boolean isAvailable(int howMany) {
//         return getAvailable() - howMany >= 0;
//     }
// 
// }


// Path: inventory-hazelcast/src/main/java/org/myeslib/example/hazelcast/routes/HzConsumeEventsRoute.java
import java.util.List;
import java.util.UUID;
import java.util.Vector;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
import org.myeslib.core.data.Snapshot;
import org.myeslib.core.storage.SnapshotReader;
import org.myeslib.example.SampleDomain.InventoryItemAggregateRoot;
import com.google.inject.Inject;
import com.hazelcast.core.IMap;
import com.hazelcast.core.IQueue;

         .parallelProcessing()
         .streaming()
        //.log("received ${body}")
        .process(new Processor() {
            @Override
            public void process(Exchange e) throws Exception {
                UUID id = e.getIn().getBody(UUID.class);
                Snapshot<InventoryItemAggregateRoot> snapshot = snapshotReader.get(id);
                e.getOut().setHeader(ID, id);
                e.getOut().setBody(snapshot);
            }
        })
        //.log("produced ${body}")
		.to("direct:reflect-last-snapshot", "direct:reflect-query-model")
 		;
      
      from("direct:reflect-last-snapshot")
         .routeId("direct:reflect-last-snapshot")
         .process(new Processor() {
            @SuppressWarnings("unchecked")
            @Override
             public void process(Exchange e) throws Exception {
                 lastSnapshotMap.set(header(ID).evaluate(e, UUID.class), body().evaluate(e, Snapshot.class));
             }
         })
 	    ;

      from("direct:reflect-query-model")
      	.routeId("direct:reflect-query-model")
        .process(new Processor() {
			@Override