// 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);
//     }
// }


import com.cqrs.appengine.core.exceptions.AggregateNotFoundException;
import com.cqrs.appengine.core.exceptions.EventCollisionException;
import com.cqrs.appengine.core.exceptions.HydrationException;
package com.cqrs.appengine.core.messaging;


/**
 * Interface for a simple message bus
 */
public interface MessageBus{

    /**
     * Register a command handler
     * 
     * @param aClass
     * @param handler
     */
    <T extends Command> void registerCommandHandler(Class<T> aClass, CommandHandler<T> handler);

    /**
     * Register an event handler
     * 
     * @param aClass
     * @param handler
     */
    <T extends Event, H extends EventHandler<T>> void registerEventHandler(Class<T> aClass, Class<H> handler);

    /**
     * Publish an event to the default queue
     * 
     * @param event
     */
    <T extends Event> void publish(T event);

    /**
     * Publish an event to the specified queue
     * 
     * @param event
     * @param queue
     */
    <T extends Event> void publish(T event, String queue);

    /**
     * Execute a command
     * 
     * @param command
     * @throws EventCollisionException
     * @throws HydrationException
     * @throws AggregateNotFoundException
     */
// 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/MessageBus.java
import com.cqrs.appengine.core.exceptions.AggregateNotFoundException;
import com.cqrs.appengine.core.exceptions.EventCollisionException;
import com.cqrs.appengine.core.exceptions.HydrationException;

package com.cqrs.appengine.core.messaging;


/**
 * Interface for a simple message bus
 */
public interface MessageBus{

    /**
     * Register a command handler
     * 
     * @param aClass
     * @param handler
     */
    <T extends Command> void registerCommandHandler(Class<T> aClass, CommandHandler<T> handler);

    /**
     * Register an event handler
     * 
     * @param aClass
     * @param handler
     */
    <T extends Event, H extends EventHandler<T>> void registerEventHandler(Class<T> aClass, Class<H> handler);

    /**
     * Publish an event to the default queue
     * 
     * @param event
     */
    <T extends Event> void publish(T event);

    /**
     * Publish an event to the specified queue
     * 
     * @param event
     * @param queue
     */
    <T extends Event> void publish(T event, String queue);

    /**
     * Execute a command
     * 
     * @param command
     * @throws EventCollisionException
     * @throws HydrationException
     * @throws AggregateNotFoundException
     */
    <T extends Command> void send(T command) throws EventCollisionException, HydrationException, AggregateNotFoundException;