// Path: src/main/java/com/cqrs/appengine/core/domain/AggregateRoot.java
// public interface AggregateRoot {
// 
//     /**
//      * get the Id
//      * 
//      * @return
//      */
//     UUID getId();
// 
//     /**
//      * Gets all change events since the
//      * original hydration. If there are no
//      * changes then null is returned
//      * 
//      * @return
//      */
//     Iterable<Event> getUncommittedChanges();
// 
//     /**
//      * Mark all changes a committed
//      */
//     void markChangesAsCommitted();
// 
//     /**
//      * load the aggregate root
//      * 
//      * @param history
//      * @throws HydrationException 
//      */
//     void loadFromHistory(Iterable<Event> history) throws HydrationException;
// 
//     /**
//      * Returns the version of the aggregate when it was hydrated
//      * @return
//      */
//     int getExpectedVersion();
// }
// 
// Path: src/main/java/com/cqrs/appengine/core/exceptions/AggregateNotFoundException.java
// public class AggregateNotFoundException extends AggregateException {
// 
// 	private static final String ERROR_TEXT = "The aggregate you requested cannot be found.";
// 	
// 	private static final long serialVersionUID = 1L;
// 
// 	/**
// 	 * Constructor
// 	 * 
// 	 * @param aggregateId
// 	 */
// 	public AggregateNotFoundException(UUID aggregateId) {
// 		super(aggregateId, ERROR_TEXT);
// 	}
// 
// }
// 
// Path: src/main/java/com/cqrs/appengine/core/exceptions/EventCollisionException.java
// public class EventCollisionException extends AggregateException {
// 
//     private static final String ERROR_TEXT = "Data has been changed between loading and state changes.";
// 
//     private static final long serialVersionUID = 1L;
// 
//     private int expectedVersion;
//     private Date dateOccurred;
// 
//     /**
//      * Constructor
//      * 
//      * @param aggregateId
//      * @param expectedVersion
//      */
//     public EventCollisionException(UUID aggregateId, int expectedVersion){
//         this(aggregateId, expectedVersion, ERROR_TEXT);
//     }
//     
//     /**
//      * Constructor
//      * 
//      * @param aggregateId
//      * @param expectedVersion
//      * @param message
//      */
//     public EventCollisionException(UUID aggregateId, int expectedVersion, String message){
//         super(aggregateId, message);
//         this.expectedVersion = expectedVersion;
//         this.dateOccurred = new Date();
//     }
// 
//     /**
//      * Get the expected version when the collision occurred
//      * 
//      * @return
//      */
//     public int getExpectedVersion(){
//         return expectedVersion;
//     }
// 
//     /**
//      * Get the date the exception occurred
//      * 
//      * @return
//      */
//     public Date getDateOccurred(){
//         return dateOccurred;
//     }
// }
// 
// Path: src/main/java/com/cqrs/appengine/core/exceptions/HydrationException.java
// public class HydrationException extends AggregateException {
// 
//     private static final String ERROR_TEXT = "Loading the data failed";
// 
//     private static final long serialVersionUID = 1L;
// 
//     /**
//      * Default constructor
//      * 
//      * @param aggregateId
//      */
//     public HydrationException(UUID aggregateId){
//         super(aggregateId, ERROR_TEXT);
//     }
// 
//     /**
//      * Constructor to provide specific error reason for the hydration exception
//      * 
//      * @param aggregateId
//      * @param error
//      */
//     public HydrationException(UUID aggregateId, String error){
//         super(aggregateId, error);
//     }
// }
// 
// Path: src/main/java/com/cqrs/appengine/core/messaging/Event.java
// public interface Event {
// 
// }


import java.util.UUID;
import com.cqrs.appengine.core.domain.AggregateRoot;
import com.cqrs.appengine.core.exceptions.AggregateNotFoundException;
import com.cqrs.appengine.core.exceptions.EventCollisionException;
import com.cqrs.appengine.core.exceptions.HydrationException;
import com.cqrs.appengine.core.messaging.Event;
package com.cqrs.appengine.core.persistence;



/**
 * Implementation of a simple event repository
 * 
 * @param <T>
 */
public class EventRepository<T extends AggregateRoot> implements Repository<T> {

    /**
     * Instance of the event store
     */
    private EventStore eventStore;

    /**
     * The class type that the repository is working with
     */
    private Class<T> aClass;

    /**
     * Default Constructor
     * 
     * @param aClass
     */
    public EventRepository(Class<T> aClass){
        this.aClass = aClass;
        eventStore = new AppEngineEventStore();
    }

    /**
     * Constructor to be used when specifying a specific
     * queue for events to be published to
     * 
     * @param aClass
     */
    public EventRepository(Class<T> aClass, String queue){
        this.aClass = aClass;
        eventStore = new AppEngineEventStore(queue);
    }

    @Override
// Path: src/main/java/com/cqrs/appengine/core/domain/AggregateRoot.java
// public interface AggregateRoot {
// 
//     /**
//      * get the Id
//      * 
//      * @return
//      */
//     UUID getId();
// 
//     /**
//      * Gets all change events since the
//      * original hydration. If there are no
//      * changes then null is returned
//      * 
//      * @return
//      */
//     Iterable<Event> getUncommittedChanges();
// 
//     /**
//      * Mark all changes a committed
//      */
//     void markChangesAsCommitted();
// 
//     /**
//      * load the aggregate root
//      * 
//      * @param history
//      * @throws HydrationException 
//      */
//     void loadFromHistory(Iterable<Event> history) throws HydrationException;
// 
//     /**
//      * Returns the version of the aggregate when it was hydrated
//      * @return
//      */
//     int getExpectedVersion();
// }
// 
// Path: src/main/java/com/cqrs/appengine/core/exceptions/AggregateNotFoundException.java
// public class AggregateNotFoundException extends AggregateException {
// 
// 	private static final String ERROR_TEXT = "The aggregate you requested cannot be found.";
// 	
// 	private static final long serialVersionUID = 1L;
// 
// 	/**
// 	 * Constructor
// 	 * 
// 	 * @param aggregateId
// 	 */
// 	public AggregateNotFoundException(UUID aggregateId) {
// 		super(aggregateId, ERROR_TEXT);
// 	}
// 
// }
// 
// Path: src/main/java/com/cqrs/appengine/core/exceptions/EventCollisionException.java
// public class EventCollisionException extends AggregateException {
// 
//     private static final String ERROR_TEXT = "Data has been changed between loading and state changes.";
// 
//     private static final long serialVersionUID = 1L;
// 
//     private int expectedVersion;
//     private Date dateOccurred;
// 
//     /**
//      * Constructor
//      * 
//      * @param aggregateId
//      * @param expectedVersion
//      */
//     public EventCollisionException(UUID aggregateId, int expectedVersion){
//         this(aggregateId, expectedVersion, ERROR_TEXT);
//     }
//     
//     /**
//      * Constructor
//      * 
//      * @param aggregateId
//      * @param expectedVersion
//      * @param message
//      */
//     public EventCollisionException(UUID aggregateId, int expectedVersion, String message){
//         super(aggregateId, message);
//         this.expectedVersion = expectedVersion;
//         this.dateOccurred = new Date();
//     }
// 
//     /**
//      * Get the expected version when the collision occurred
//      * 
//      * @return
//      */
//     public int getExpectedVersion(){
//         return expectedVersion;
//     }
// 
//     /**
//      * Get the date the exception occurred
//      * 
//      * @return
//      */
//     public Date getDateOccurred(){
//         return dateOccurred;
//     }
// }
// 
// Path: src/main/java/com/cqrs/appengine/core/exceptions/HydrationException.java
// public class HydrationException extends AggregateException {
// 
//     private static final String ERROR_TEXT = "Loading the data failed";
// 
//     private static final long serialVersionUID = 1L;
// 
//     /**
//      * Default constructor
//      * 
//      * @param aggregateId
//      */
//     public HydrationException(UUID aggregateId){
//         super(aggregateId, ERROR_TEXT);
//     }
// 
//     /**
//      * Constructor to provide specific error reason for the hydration exception
//      * 
//      * @param aggregateId
//      * @param error
//      */
//     public HydrationException(UUID aggregateId, String error){
//         super(aggregateId, error);
//     }
// }
// 
// Path: src/main/java/com/cqrs/appengine/core/messaging/Event.java
// public interface Event {
// 
// }


// Path: src/main/java/com/cqrs/appengine/core/persistence/EventRepository.java
import java.util.UUID;
import com.cqrs.appengine.core.domain.AggregateRoot;
import com.cqrs.appengine.core.exceptions.AggregateNotFoundException;
import com.cqrs.appengine.core.exceptions.EventCollisionException;
import com.cqrs.appengine.core.exceptions.HydrationException;
import com.cqrs.appengine.core.messaging.Event;

package com.cqrs.appengine.core.persistence;



/**
 * Implementation of a simple event repository
 * 
 * @param <T>
 */
public class EventRepository<T extends AggregateRoot> implements Repository<T> {

    /**
     * Instance of the event store
     */
    private EventStore eventStore;

    /**
     * The class type that the repository is working with
     */
    private Class<T> aClass;

    /**
     * Default Constructor
     * 
     * @param aClass
     */
    public EventRepository(Class<T> aClass){
        this.aClass = aClass;
        eventStore = new AppEngineEventStore();
    }

    /**
     * Constructor to be used when specifying a specific
     * queue for events to be published to
     * 
     * @param aClass
     */
    public EventRepository(Class<T> aClass, String queue){
        this.aClass = aClass;
        eventStore = new AppEngineEventStore(queue);
    }

    @Override
    public void save(T aggregate) throws EventCollisionException {