// Path: src/main/java/com/cqrs/appengine/core/StringHelper.java
// public class StringHelper {
// 	
// 	public static boolean IsNullOrWhitespace(String text)
// 	{
// 		return text == null || text.isEmpty() || text.trim().length() == 0;
// 	}
// }
// 
// Path: src/main/java/com/cqrs/appengine/core/domain/AggregateRootBase.java
// public abstract class AggregateRootBase implements AggregateRoot {
// 
//     /**
//      * Aggregate id
//      */
//     protected UUID id = null;
// 
//     /**
//      * list of changes that have occurred since last loaded
//      */
//     private List<Event> changes = new ArrayList<Event>();
// 
//     /**
//      * returns the expected version
//      */
//     private int expectedVersion = 0;
// 
//     @Override
//     public int getExpectedVersion(){
//         return expectedVersion;
//     }
// 
//     @Override
//     public void markChangesAsCommitted(){
//         changes.clear();
//     } 
// 
//     @Override
//     public UUID getId(){
//         return id;
//     }
// 
//     @Override
//     public Iterable<Event> getUncommittedChanges(){
//         return changes == null || changes.isEmpty() ? null : changes;
//     }
// 
//     @Override
//     public void loadFromHistory(Iterable<Event> history) throws HydrationException {
// 
//         if(history != null){
//             for(Event event : history){
//                 applyChange(event, false);
//                 expectedVersion++;
//             }
//         }
//     }
// 
//     /**
//      * Apply the event assuming it is new
//      * 
//      * @param event
//      * @throws HydrationException 
//      */
//     protected void applyChange(Event event) throws HydrationException {
//         applyChange(event,true);
//     }
// 
//     /**
//      * Apply the change by invoking the inherited members apply method that fits the signature of the event passed
//      * 
//      * @param event
//      * @param isNew
//      * @throws HydrationException 
//      */
//     private void applyChange(Event event, boolean isNew) throws HydrationException {
// 
//         Method method = null;
// 
//         try {
//             method = this.getClass().getDeclaredMethod("apply", event.getClass());
//         } catch (NoSuchMethodException e) {
//             //do nothing. This just means that the method signature wasn't found and
//             //the aggregate doesn't need to apply any state changes since it wasn't
//             //implemented.
//         }
// 
//         if(method != null){
//             method.setAccessible(true);
//             try {
//                 method.invoke(this,event);
//             } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
//                 throw new HydrationException(this.getId(), e.getMessage());
//             }		
//         }
// 
//         if(isNew){
//             changes.add(event);
//         }
//     }
// }
// 
// 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 java.util.UUID;
import com.cqrs.appengine.core.StringHelper;
import com.cqrs.appengine.core.domain.AggregateRootBase;
import com.cqrs.appengine.core.exceptions.HydrationException;
package com.cqrs.appengine.sample.domain;



/**
 * Class that represents an attendee at a conference
 */
public class Attendee extends AggregateRootBase {

    /**
     * Flag that determines if the attendee is enabled
     */
    private boolean isEnabled = true;
    
    /**
     * Id used to confirm an email change request
     */
    private UUID confirmationId = null;
    
    /**
     * Email address the user has requested a change to
     */
    private String unconfirmedEmail = null;
    
    /**
     * Default constructor. 
     */
    public Attendee() {	
    }

    /**
     * Constructor used when creating a new attendee
     * 
     * @param attendeeId
     * @param email
     * @param firstName
     * @param lastName
     * @throws HydrationException 
     */
    private Attendee(UUID attendeeId, String email, String firstName, String lastName) throws HydrationException {
        applyChange(new AttendeeRegistered(attendeeId, email, firstName, lastName));
    }

    /**
     * Change the attendee's name
     * 
     * @param firstName
     * @param lastName
     * @throws IllegalArgumentException
     * @throws HydrationException 
     */
    public void changeName(String firstName, String lastName) throws HydrationException {

        /*
         * Don't bother checking for parameter validity if the attendee isn't enabled
         */
    	if(!isEnabled) throw new IllegalStateException("Operation not allowed. The attendee is disabled");

        /*
         * Only change state if the data is valid 
         */
// Path: src/main/java/com/cqrs/appengine/core/StringHelper.java
// public class StringHelper {
// 	
// 	public static boolean IsNullOrWhitespace(String text)
// 	{
// 		return text == null || text.isEmpty() || text.trim().length() == 0;
// 	}
// }
// 
// Path: src/main/java/com/cqrs/appengine/core/domain/AggregateRootBase.java
// public abstract class AggregateRootBase implements AggregateRoot {
// 
//     /**
//      * Aggregate id
//      */
//     protected UUID id = null;
// 
//     /**
//      * list of changes that have occurred since last loaded
//      */
//     private List<Event> changes = new ArrayList<Event>();
// 
//     /**
//      * returns the expected version
//      */
//     private int expectedVersion = 0;
// 
//     @Override
//     public int getExpectedVersion(){
//         return expectedVersion;
//     }
// 
//     @Override
//     public void markChangesAsCommitted(){
//         changes.clear();
//     } 
// 
//     @Override
//     public UUID getId(){
//         return id;
//     }
// 
//     @Override
//     public Iterable<Event> getUncommittedChanges(){
//         return changes == null || changes.isEmpty() ? null : changes;
//     }
// 
//     @Override
//     public void loadFromHistory(Iterable<Event> history) throws HydrationException {
// 
//         if(history != null){
//             for(Event event : history){
//                 applyChange(event, false);
//                 expectedVersion++;
//             }
//         }
//     }
// 
//     /**
//      * Apply the event assuming it is new
//      * 
//      * @param event
//      * @throws HydrationException 
//      */
//     protected void applyChange(Event event) throws HydrationException {
//         applyChange(event,true);
//     }
// 
//     /**
//      * Apply the change by invoking the inherited members apply method that fits the signature of the event passed
//      * 
//      * @param event
//      * @param isNew
//      * @throws HydrationException 
//      */
//     private void applyChange(Event event, boolean isNew) throws HydrationException {
// 
//         Method method = null;
// 
//         try {
//             method = this.getClass().getDeclaredMethod("apply", event.getClass());
//         } catch (NoSuchMethodException e) {
//             //do nothing. This just means that the method signature wasn't found and
//             //the aggregate doesn't need to apply any state changes since it wasn't
//             //implemented.
//         }
// 
//         if(method != null){
//             method.setAccessible(true);
//             try {
//                 method.invoke(this,event);
//             } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
//                 throw new HydrationException(this.getId(), e.getMessage());
//             }		
//         }
// 
//         if(isNew){
//             changes.add(event);
//         }
//     }
// }
// 
// 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/sample/domain/Attendee.java
import java.util.UUID;
import com.cqrs.appengine.core.StringHelper;
import com.cqrs.appengine.core.domain.AggregateRootBase;
import com.cqrs.appengine.core.exceptions.HydrationException;

package com.cqrs.appengine.sample.domain;



/**
 * Class that represents an attendee at a conference
 */
public class Attendee extends AggregateRootBase {

    /**
     * Flag that determines if the attendee is enabled
     */
    private boolean isEnabled = true;
    
    /**
     * Id used to confirm an email change request
     */
    private UUID confirmationId = null;
    
    /**
     * Email address the user has requested a change to
     */
    private String unconfirmedEmail = null;
    
    /**
     * Default constructor. 
     */
    public Attendee() {	
    }

    /**
     * Constructor used when creating a new attendee
     * 
     * @param attendeeId
     * @param email
     * @param firstName
     * @param lastName
     * @throws HydrationException 
     */
    private Attendee(UUID attendeeId, String email, String firstName, String lastName) throws HydrationException {
        applyChange(new AttendeeRegistered(attendeeId, email, firstName, lastName));
    }

    /**
     * Change the attendee's name
     * 
     * @param firstName
     * @param lastName
     * @throws IllegalArgumentException
     * @throws HydrationException 
     */
    public void changeName(String firstName, String lastName) throws HydrationException {

        /*
         * Don't bother checking for parameter validity if the attendee isn't enabled
         */
    	if(!isEnabled) throw new IllegalStateException("Operation not allowed. The attendee is disabled");

        /*
         * Only change state if the data is valid 
         */
        if(!StringHelper.IsNullOrWhitespace(firstName) && !StringHelper.IsNullOrWhitespace(lastName)) {