gt: 		Workout w = new Workout(this.name, fExList);
context: /**
   * 
   * This is OpenTraining, an Android application for planning your your fitness training.
   * Copyright (C) 2012-2014 Christian Skubich
   * 
   * This program is free software: you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   * 
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   * 
   * You should have received a copy of the GNU General Public License
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   * 
   */
  
  package de.skubware.opentraining.basic;
  
  import android.util.Log;
  
  import java.io.Serializable;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.Date;
  import java.util.Iterator;
  import java.util.List;
  
  import de.skubware.opentraining.Exceptions.ErrorException;
  
  /**
   * This class represents a single workout. A workout needs a name and consists
   * out of more than one {@code FitnessExercise}s.
   * 
   * It is possible to iterate through the {@code FitnessExercises} and to add new
   * ones.
   * 
   * @author Christian Skubich
   * 
   */
  public class Workout implements Iterable<FitnessExercise>, Serializable {
  	/** Default serialVersionUID */
  	private static final long serialVersionUID = 1L;
  
  	/** Tag for logging */
  	static final String TAG = "Workout";
  
  	/**
  	 * @field DEFAULT_EMPTYROWS
  	 */
  	public static int DEFAULT_EMPTYROWS = 8;
  
  	private String name;
  	private int emptyRows = DEFAULT_EMPTYROWS;
  	private ArrayList<FitnessExercise> fitnessExercises = new ArrayList<FitnessExercise>();
  
  	/**
  	 * Constructor of this class.
  	 * 
  	 * @param name
  	 *            The name of the workout
  	 * @param fExes
  	 *            The FitnessExercises of the workout
  	 * 
  	 * @throws ErrorException
  	 *             if any argument is null or empty
  	 * 
  	 */
  	public Workout(String name, Collection<FitnessExercise> fExes) throws ErrorException {
  		if (name == null || name.replaceAll(" ", "").equals("") || fExes == null || fExes.isEmpty() || fExes.contains(null)) {
  			throw new ErrorException();
  		}
  
  		// Assign given values
  		this.name = name;
  		this.fitnessExercises = new ArrayList<FitnessExercise>();
  		this.fitnessExercises.addAll(fExes);
  	}
  
  	/**
  	 * @see #Workout(String, Collection<FitnessExercise>)
  	 */
  	public Workout(String name, FitnessExercise... fExes) throws ErrorException {
  		this(name, Arrays.asList(fExes));
  	}
  
  	/**
  	 * Alternative constructor of this class for given ExerciseTypes. Have a
  	 * look at @see #Workout(String, Collection<FitnessExercise>) for more
  	 * information.
  	 * 
  	 * @param name
  	 *            The name of the workout
  	 * @param exes
  	 *            The ExerciseTypes that should be added to workout.
  	 */
  	public Workout(String name, List<ExerciseType> exes) throws ErrorException {
  		this(name, ExerciseType.asFitnessExercise(exes));
  	}
  
  	/** {@inheritDoc} */
  	public Iterator<FitnessExercise> iterator() {
  		return this.fitnessExercises.iterator();
  	}
  
  	/**
  	 * @see java.util.List#contains(Object)
  	 */
  	public boolean contains(FitnessExercise fEx) {
  		return this.fitnessExercises.contains(fEx);
  	}
  
  	/** Adds a new TrainingEntriy to each FitnessExercise in this Workout. */
  	public void addTrainingEntry(Date date) {
  		for (FitnessExercise fEx : this.fitnessExercises) {
  			fEx.addTrainingEntry(date);
  		}
  	}
  
  	/**
  	 * Returns a set of dates, for which {@link TrainingEntry}s do exist.
  	 * 
  	 * @return A set of dates, for which training entries do exist.
  	 */
  
  	/**
  	 * Checks if there are TrainingEntries for the FitnessExercises.
  	 * 
  	 * @return True if the FitnessExercises have at least one TrainingEntry
  	 */
  	public boolean hasTrainingEntries() {
  		return this.fitnessExercises.get(0).getTrainingEntryList().size() > 0;
  	}
  
  	/**
  	 * Getter for name
  	 * 
  	 * @return The name of the workout
  	 */
  	public String getName() {
  		return this.name;
  	}
  
  	/**
  	 * Setter for name
  	 * 
  	 * @param name
  	 *            The new name of the workout
  	 */
  	public void setName(String name) {
  		this.name = name;
  	}
  
  	/**
  	 * Getter for the {@code FitnessExercises}
  	 * 
  	 * @return A list with the FitnessExercises
  	 */
  	public List<FitnessExercise> getFitnessExercises() {
  		return this.fitnessExercises;
  	}
  
  	/**
  	 * Adds the given {@code FitnessExercise} to the Workout.
  	 * 
  	 * @param fEx
  	 *            The FitnessExercise to add
  	 * 
  	 * @throws IllegalArgumentException
  	 *             if there is already an FitnessExercise with the same
  	 *             ExerciseType
  	 */
  	public void addFitnessExercise(FitnessExercise fEx) {
  		ExerciseType exType = fEx.getExType();
  		for (FitnessExercise ex : this.getFitnessExercises()) {
  			if (ex.getExType().equals(exType)) {
  				throw new IllegalArgumentException("There is already an Exercise with the ExerciseType: " + exType.toString());
  			}
  		}
  
  		this.fitnessExercises.add(fEx);
  	}
  
  	/**
  	 * Removes the given {@code FitnessExercise} from the Workout.
  	 * 
  	 * @param fEx
  	 *            The FitnessExercise to remove
  	 */
  	public void removeFitnessExercise(FitnessExercise fEx) {
  		this.fitnessExercises.remove(fEx);
  	}
  
  	/**
  	 * Updates the {@link FitnessExercise}.
  	 * 
  	 * @param changedFEx
  	 *            The FitnessExercise that has changed
  	 * 
  	 * @throws IllegalArgumentException
  	 *             if the Exercise is not contained in this Workout
  	 */
  	public void updateFitnessExercise(FitnessExercise changedFEx) {
  		Log.d(TAG, "updateFitnessExercise(), changedFEx: " + changedFEx.toDebugString());
  		FitnessExercise oldFex = null;
  		for (FitnessExercise fEx : this.fitnessExercises) {
  			// this comparison relies on the fact that each Workout can only
  			// contain each ExerciseType once
  			if (fEx.getExType().equals(changedFEx.getExType())) {
  				oldFex = changedFEx;
  				int oldIndex = fitnessExercises.indexOf(fEx);
  				fitnessExercises.remove(oldIndex);
  				fitnessExercises.add(oldIndex, changedFEx);
  				break;
  			}
  		}
  
  		if (oldFex == null) {
  			throw new IllegalArgumentException("FitnessExercise: " + changedFEx.toString() + " is not contained in this Workout: "
  					+ this.toString());
  		}
  
  	}
  
  	/** {@inheritDoc} */
  	@Override
  	public boolean equals(Object o) {
  		if (!(o instanceof Workout)) {
  			return false;
  		}
  		Workout w = (Workout) o;
  
  		// hashCode() check
  		if (this.hashCode() != w.hashCode()) {
  			return false;
  		}
  
  		// name check
  		if (!w.getName().equals(this.getName())) {
  			return false;
  		}
  
  		// FitnessExercise check
  		if (w.getFitnessExercises().containsAll(this.fitnessExercises)) {
  			return false;
  		}
  		if (this.fitnessExercises.containsAll(w.getFitnessExercises())) {
  			return true;
  		} else {
  			return false;
  		}
  
  	}
  
  	/** {@inheritDoc} */
  	@Override
  	public int hashCode() {
  		return this.name.hashCode() + this.fitnessExercises.size();
  	}
  
  	/** {@inheritDoc} */
  	@Override
  	public String toString() {
  		return this.name;
  	}
  
  	/**
  	 * Returns a String that represents this object. Should only be used for
  	 * debugging.
  	 * 
  	 * @return A String that represents this object.
  	 */
  	public String toDebugString() {
  		StringBuilder builder = new StringBuilder();
  
  		builder.append("Name: " + name + "\n");
  		builder.append("Empty Rows: " + emptyRows + "\n");
  		for (FitnessExercise fEx : getFitnessExercises()) {
  			builder.append("\n" + fEx.toDebugString());
  		}
  
  		return builder.toString();
  	}
  
  	public void switchExercises(FitnessExercise first, FitnessExercise second) {
  		if (!this.fitnessExercises.contains(first) || !this.fitnessExercises.contains(second)) {
  			throw new AssertionError("FitnessExercise does not exist in workout");
  		}
  
  		int idxFirst = this.fitnessExercises.indexOf(first);
  		int idxSecond = this.fitnessExercises.indexOf(second);
  
  		Collections.swap(fitnessExercises, idxFirst, idxSecond);
  
  	}
  
  	/**
  	 * Getter for emptyRows
  	 * 
  	 * @return The number of empty rows (>0)
  	 */
  	public int getEmptyRows() {
  		return this.emptyRows;
  	}
  
  	/**
  	 * Setter for emptyRows
  	 * 
  	 * @param emptyRows
  	 *            New number of empty rows, must be positive
  	 * 
  	 * @throws IllegalArgumentException
  	 *             if argument is below 0
  	 */
  	public void setEmptyRows(int emptyRows) {
  		if (emptyRows > 0) {
  			this.emptyRows = emptyRows;
  		} else {
  			throw new IllegalArgumentException("There must be more than 0 empty rows");
  		}
  
  		Log.d(TAG, "setEmptyRows() to " + this.emptyRows);
  	}
  
  	/**
  	  * Returns a new Workout only containing the Exercises, but no history(FSets).
  	  * The crated Workout will have the same name.
  	  */
  	public Workout getWorkoutWithoutHistory() throws ErrorException{
  		List<FitnessExercise> fExList = new ArrayList<FitnessExercise>();
  		for(FitnessExercise fEx: this.fitnessExercises){
  			fExList.add(new FitnessExercise(fEx.getExType())); // copy exercises without FSets
  		}
  