gt: 		for (String key : this.genes.keySet()) {
context: /**
   * Copyright 2015 George Belden
   * 
   * This file is part of DecipherEngine.
   * 
   * DecipherEngine 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.
   * 
   * DecipherEngine 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
   * DecipherEngine. If not, see <http://www.gnu.org/licenses/>.
   */
  
  package com.ciphertool.engine.entities;
  
  import java.math.BigDecimal;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.UUID;
  
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.springframework.data.annotation.Id;
  import org.springframework.data.annotation.Transient;
  import org.springframework.data.mongodb.core.index.Indexed;
  import org.springframework.data.mongodb.core.mapping.Document;
  
  import com.ciphertool.genetics.MathConstants;
  import com.ciphertool.genetics.annotations.Clean;
  import com.ciphertool.genetics.annotations.Dirty;
  import com.ciphertool.genetics.entities.Ancestry;
  import com.ciphertool.genetics.entities.Chromosome;
  import com.ciphertool.genetics.entities.Gene;
  import com.ciphertool.genetics.entities.KeyedChromosome;
  import com.ciphertool.genetics.population.Population;
  
  @Document(collection = "solutions")
  public class CipherKeyChromosome implements KeyedChromosome<String> {
  	private static Logger		log					= LoggerFactory.getLogger(CipherKeyChromosome.class);
  
  	@Transient
  	private static final int	KEY_SIZE			= 54;
  
  	/**
  	 * This initial value is only used as a unique identifier for the Chromosome's ancestry, but a different generated
  	 * ID is persisted to database.
  	 */
  	@Id
  	protected String			id					= UUID.randomUUID().toString();
  
  	@Indexed(background = true)
  	protected Integer			solutionSetId;
  
  	protected Cipher			cipher;
  
  	@Transient
  	private Ancestry			ancestry;
  
  	@Transient
  	protected boolean			evaluationNeeded	= true;
  
  	@Transient
  	private BigDecimal			fitness				= BigDecimal.ZERO;
  
  	@Transient
  	private int					age					= 0;
  
  	@Transient
  	private int					numberOfChildren	= 0;
  
  	private Map<String, Gene>	genes;
  
  	@Transient
  	private Population			population;
  
  	public CipherKeyChromosome() {
  		genes = new HashMap<String, Gene>();
  	}
  
  	/**
  	 * @param cipherId
  	 *            the cipherId to set
  	 * @param rows
  	 *            the rows to set
  	 * @param columns
  	 *            the columns to set
  	 */
  	public CipherKeyChromosome(Cipher cipher, int numGenes) {
  		if (cipher == null) {
  			throw new IllegalArgumentException("Cannot construct CipherKeyChromosome with null cipher.");
  		}
  
  		this.cipher = cipher;
  
  		genes = new HashMap<String, Gene>(numGenes);
  	}
  
  	/**
  	 * @return the id
  	 */
  	public String getId() {
  		return id;
  	}
  
  	/**
  	 * @param id
  	 *            the id to set
  	 */
  	public void setId(String id) {
  		this.id = id;
  	}
  
  	@Override
  	public Integer getSolutionSetId() {
  		return solutionSetId;
  	}
  
  	@Override
  	public void setSolutionSetId(Integer solutionSetId) {
  		this.solutionSetId = solutionSetId;
  	}
  
  	/**
  	 * @return the cipher
  	 */
  	public Cipher getCipher() {
  		return this.cipher;
  	}
  
  	/**
  	 * @param cipher
  	 *            the cipher to set
  	 */
  	public void setCipher(Cipher cipher) {
  		this.cipher = cipher;
  	}
  
  	/**
  	 * @return the evaluationNeeded
  	 */
  	@Override
  	public boolean isEvaluationNeeded() {
  		return evaluationNeeded;
  	}
  
  	/**
  	 * @param evaluationNeeded
  	 *            the evaluationNeeded to set
  	 */
  	@Override
  	public void setEvaluationNeeded(boolean evaluationNeeded) {
  		this.evaluationNeeded = evaluationNeeded;
  	}
  
  	@Override
  	public BigDecimal getFitness() {
  		return fitness;
  	}
  
  	@Override
  	@Clean
  	public void setFitness(BigDecimal fitness) {
  		this.fitness = fitness;
  	}
  
  	@Override
  	public int getAge() {
  		return age;
  	}
  
  	@Override
  	public void setAge(int age) {
  		this.age = age;
  	}
  
  	@Override
  	public void increaseAge() {
  		this.age++;
  	}
  
  	@Override
  	public int getNumberOfChildren() {
  		return numberOfChildren;
  	}
  
  	@Override
  	public void setNumberOfChildren(int numberOfChildren) {
  		this.numberOfChildren = numberOfChildren;
  	}
  
  	@Override
  	public void increaseNumberOfChildren() {
  		this.numberOfChildren++;
  	}
  
  	@Override
  	public Map<String, Gene> getGenes() {
  		return Collections.unmodifiableMap(genes);
  	}
  
  	@Override
  	@Dirty
  	public void putGene(String key, Gene gene) {
  		if (null == gene) {
  			log.warn("Attempted to insert a null Gene to CipherKeyChromosome.  Returning. " + this);
  
  			return;
  		}
  
  		if (this.genes.get(key) != null) {
  			log.warn("Attempted to insert a Gene to CipherKeyChromosome with key " + key
  					+ ", but the key already exists.  If this was intentional, please use replaceGene() instead.  Returning. "
  					+ this);
  
  			return;
  		}
  
  		gene.setChromosome(this);
  
  		this.genes.put(key, gene);
  	}
  
  	@Override
  	@Dirty
  	public Gene removeGene(String key) {
  		if (null == this.genes || null == this.genes.get(key)) {
  			log.warn("Attempted to remove a Gene from CipherKeyChromosome with key " + key
  					+ ", but this key does not exist.  Returning null.");
  
  			return null;
  		}
  
  		return this.genes.remove(key);
  	}
  
  	/*
  	 * This does the same thing as putGene(), and exists solely for semantic consistency.
  	 */
  	@Override
  	@Dirty
  	public void replaceGene(String key, Gene newGene) {
  		if (null == newGene) {
  			log.warn("Attempted to replace a Gene from CipherKeyChromosome, but the supplied Gene was null.  Cannot continue. "
  					+ this);
  
  			return;
  		}
  
  		if (null == this.genes || null == this.genes.get(key)) {
  			log.warn("Attempted to replace a Gene from CipherKeyChromosome with key " + key
  					+ ", but this key does not exist.  Cannot continue.");
  
  			return;
  		}
  
  		newGene.setChromosome(this);
  
  		this.genes.put(key, newGene);
  	}
  
  	@Override
  	public Integer actualSize() {
  		return this.genes.size();
  	}
  
  	@Override
  	public Integer targetSize() {
  		return KEY_SIZE;
  	}
  
  	@Override
  	public Chromosome clone() {
  		CipherKeyChromosome copyChromosome = new CipherKeyChromosome(this.cipher, this.genes.size());
  
  		copyChromosome.setAge(0);
  		copyChromosome.setNumberOfChildren(0);
  		copyChromosome.setSolutionSetId(this.solutionSetId);
  
  		Gene nextGene = null;
  