/**
   * Create a <code>Genotype</code> from XML.
   *
   * @param generationNode XML
   * @param config
   * @param db persistence repository from which to read chromosomes
   * @return new genotype
   * @throws Exception
   */
  private static Genotype genotypeFromXml(Node generationNode, Configuration config, Persistence db)
      throws Exception {
    if (Generation.GENERATION_TAG.equals(generationNode.getNodeName()) == false)
      throw new IllegalArgumentException("node name not " + Generation.GENERATION_TAG);

    // loop through list to find chromosomes
    ArrayList chroms = new ArrayList();
    for (int generationChildIdx = 0;
        generationChildIdx < generationNode.getChildNodes().getLength();
        ++generationChildIdx) {
      Node specieNode = generationNode.getChildNodes().item(generationChildIdx);
      if (Specie.SPECIE_TAG.equals(specieNode.getNodeName())) {
        // for each specie ...
        NamedNodeMap specieAttrs = specieNode.getAttributes();
        if (specieAttrs == null) throw new IllegalArgumentException("missing specie attributes");

        // ... and loop through chromosomes
        for (int specieChildIdx = 0;
            specieChildIdx < specieNode.getChildNodes().getLength();
            ++specieChildIdx) {
          Node chromNode = specieNode.getChildNodes().item(specieChildIdx);
          if (Specie.CHROMOSOME_TAG.equals(chromNode.getNodeName())) {
            NamedNodeMap chromAttrs = chromNode.getAttributes();
            if (chromAttrs == null)
              throw new IllegalArgumentException("missing chromosome attributes");
            Node chromIdNode = chromAttrs.getNamedItem(Specie.ID_TAG);
            if (chromIdNode == null) throw new IllegalArgumentException("missing chromosome id");

            // get id and load chromosome from persistence (skip if representative since its
            // already been added
            Long chromId = Long.valueOf(chromIdNode.getNodeValue());
            Chromosome c = db.loadChromosome(chromId.toString(), config);
            if (c != null) chroms.add(c);
            else logger.warn("chromosome in run not found: " + chromId);
          }
        }
      }
    }

    // don't return empty genotype
    if (chroms.size() <= 0) return null;

    // sort in order of id so that they will be added in proper order (age)
    Collections.sort(chroms);
    return new Genotype(config, chroms);
  }