Clover coverage report - JGAP 3.1
Coverage timestamp: Mo Dez 11 2006 21:16:18 CET
file stats: LOC: 665   Methods: 9
NCLOC: 272   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
XMLManager.java 76,9% 82,9% 88,9% 82,1%
coverage coverage
 1    /*
 2    * This file is part of JGAP.
 3    *
 4    * JGAP offers a dual license model containing the LGPL as well as the MPL.
 5    *
 6    * For licencing information please see the file license.txt included with JGAP
 7    * or have a look at the top of class org.jgap.Chromosome which representatively
 8    * includes the JGAP license policy applicable for any file delivered with JGAP.
 9    */
 10    package org.jgap.xml;
 11   
 12    import java.io.*;
 13    import java.lang.reflect.*;
 14    import java.util.*;
 15    import javax.xml.parsers.*;
 16    import javax.xml.transform.*;
 17    import javax.xml.transform.dom.*;
 18    import javax.xml.transform.stream.*;
 19    import junitx.util.PrivateAccessor;
 20   
 21    import org.jgap.*;
 22    import org.w3c.dom.*;
 23   
 24    /**
 25    * The XMLManager performs marshalling of genetic entity instances
 26    * (such as Chromosomes and Genotypes) to XML representations of those
 27    * entities, as well as unmarshalling. All of the methods in this class are
 28    * static, so no construction is required (or allowed).
 29    *
 30    * @author Neil Rotstan
 31    * @author Klaus Meffert
 32    * @since 1.0
 33    */
 34    public class XMLManager {
 35   
 36    /** String containing the CVS revision. Read out via reflection!*/
 37    private final static String CVS_REVISION = "$Revision: 1.19 $";
 38   
 39    /**
 40    * Constant representing the name of the genotype XML element tag.
 41    */
 42    private static final String GENOTYPE_TAG = "genotype";
 43   
 44    /**
 45    * Constant representing the name of the chromosome XML element tag.
 46    */
 47    private static final String CHROMOSOME_TAG = "chromosome";
 48   
 49    /**
 50    * Constant representing the name of the gene XML element tag.
 51    */
 52    private static final String GENES_TAG = "genes";
 53   
 54    /**
 55    * Constant representing the name of the gene XML element tag.
 56    */
 57    private static final String GENE_TAG = "gene";
 58   
 59    private static final String ALLELE_TAG = "allele";
 60   
 61    /**
 62    * Constant representing the name of the size XML attribute that is
 63    * added to genotype and chromosome elements to describe their size.
 64    */
 65    private static final String SIZE_ATTRIBUTE = "size";
 66   
 67    /**
 68    * Constant representing the fully-qualified name of the concrete
 69    * Gene class that was marshalled.
 70    */
 71    private static final String CLASS_ATTRIBUTE = "class";
 72   
 73    /**
 74    * Shared DocumentBuilder, which is used to create new DOM Document
 75    * instances.
 76    */
 77    private static final DocumentBuilder m_documentCreator;
 78   
 79    /**
 80    * Shared lock object used for synchronization purposes.
 81    */
 82    private static final Object m_lock = new Object();
 83   
 84    /**
 85    * @author Neil Rotstan
 86    * @since 1.0
 87    */
 88    static {
 89  1 try {
 90  1 m_documentCreator =
 91    DocumentBuilderFactory.newInstance().newDocumentBuilder();
 92    }
 93    catch (ParserConfigurationException parserError) {
 94  0 throw new RuntimeException(
 95    "XMLManager: Unable to setup DocumentBuilder: "
 96    + parserError.getMessage());
 97    }
 98    }
 99   
 100    /**
 101    * Private constructor. All methods in this class are static, so no
 102    * construction is allowed.
 103    */
 104  0 private XMLManager() {
 105    }
 106   
 107    /**
 108    * Marshall a Chromosome instance to an XML Document representation,
 109    * including its contained Gene instances.
 110    *
 111    * @param a_subject the chromosome to represent as an XML document
 112    * @return a Document object representing the given Chromosome
 113    *
 114    * @author Neil Rotstan
 115    * @since 1.0
 116    * @deprecated use XMLDocumentBuilder instead
 117    */
 118    public static Document representChromosomeAsDocument(final IChromosome
 119    a_subject) {
 120    // DocumentBuilders do not have to be thread safe, so we have to
 121    // protect creation of the Document with a synchronized block.
 122    // -------------------------------------------------------------
 123    Document chromosomeDocument;
 124    synchronized (m_lock) {
 125    chromosomeDocument = m_documentCreator.newDocument();
 126    }
 127    Element chromosomeElement =
 128    representChromosomeAsElement(a_subject, chromosomeDocument);
 129    chromosomeDocument.appendChild(chromosomeElement);
 130    return chromosomeDocument;
 131    }
 132   
 133    /**
 134    * Marshall a Genotype to an XML Document representation, including its
 135    * population of Chromosome instances.
 136    *
 137    * @param a_subject the genotype to represent as an XML document
 138    * @return a Document object representing the given Genotype
 139    *
 140    * @author Neil Rotstan
 141    * @since 1.0
 142    * @deprecated use XMLDocumentBuilder instead
 143    */
 144    public static Document representGenotypeAsDocument(final Genotype a_subject) {
 145    // DocumentBuilders do not have to be thread safe, so we have to
 146    // protect creation of the Document with a synchronized block.
 147    // -------------------------------------------------------------
 148    Document genotypeDocument;
 149    synchronized (m_lock) {
 150    genotypeDocument = m_documentCreator.newDocument();
 151    }
 152    Element genotypeElement =
 153    representGenotypeAsElement(a_subject, genotypeDocument);
 154    genotypeDocument.appendChild(genotypeElement);
 155    return genotypeDocument;
 156    }
 157   
 158    /**
 159    * Marshall an array of Genes to an XML Element representation.
 160    *
 161    * @param a_geneValues the genes to represent as an XML element
 162    * @param a_xmlDocument a Document instance that will be used to create
 163    * the Element instance. Note that the element will NOT be added to the
 164    * document by this method
 165    * @return an Element object representing the given genes
 166    *
 167    * @author Neil Rotstan
 168    * @author Klaus Meffert
 169    * @since 1.0
 170    * @deprecated use XMLDocumentBuilder instead
 171    */
 172    public static Element representGenesAsElement(final Gene[] a_geneValues,
 173    final Document a_xmlDocument) {
 174    // Create the parent genes element.
 175    // --------------------------------
 176    Element genesElement = a_xmlDocument.createElement(GENES_TAG);
 177    // Now add gene sub-elements for each gene in the given array.
 178    // -----------------------------------------------------------
 179    Element geneElement;
 180    for (int i = 0; i < a_geneValues.length; i++) {
 181    // Create the allele element for this gene.
 182    // ----------------------------------------
 183    geneElement = a_xmlDocument.createElement(GENE_TAG);
 184    // Add the class attribute and set its value to the class
 185    // name of the concrete class representing the current Gene.
 186    // ---------------------------------------------------------
 187    geneElement.setAttribute(CLASS_ATTRIBUTE,
 188    a_geneValues[i].getClass().getName());
 189    // Create a text node to contain the string representation of
 190    // the gene's value (allele).
 191    // ----------------------------------------------------------
 192    Element alleleRepresentation = representAlleleAsElement(a_geneValues[i],
 193    a_xmlDocument);
 194    // And now add the text node to the gene element, and then
 195    // add the gene element to the genes element.
 196    // -------------------------------------------------------
 197    geneElement.appendChild(alleleRepresentation);
 198    genesElement.appendChild(geneElement);
 199    }
 200    return genesElement;
 201    }
 202   
 203    /**
 204    *
 205    * @param a_gene Gene
 206    * @param a_xmlDocument Document
 207    * @return Element
 208    *
 209    * @author Klaus Meffert
 210    * @since 2.0
 211    */
 212  127 private static Element representAlleleAsElement(final Gene a_gene,
 213    final Document a_xmlDocument) {
 214  127 Element alleleElement = a_xmlDocument.createElement(ALLELE_TAG);
 215  127 alleleElement.setAttribute("class", a_gene.getClass().getName());
 216  127 alleleElement.setAttribute("value", a_gene.getPersistentRepresentation());
 217  127 return alleleElement;
 218    }
 219   
 220    /**
 221    * Marshall a Chromosome instance to an XML Element representation,
 222    * including its contained Genes as sub-elements. This may be useful in
 223    * scenarios where representation as an entire Document is undesirable,
 224    * such as when the representation of this Chromosome is to be combined
 225    * with other elements in a single Document.
 226    *
 227    * @param a_subject the chromosome to represent as an XML element
 228    * @param a_xmlDocument a Document instance that will be used to create
 229    * the Element instance. Note that the element will NOT be added to the
 230    * document by this method
 231    * @return an Element object representing the given Chromosome
 232    *
 233    * @author Neil Rotstan
 234    * @since 1.0
 235    * @deprecated use XMLDocumentBuilder instead
 236    */
 237    public static Element representChromosomeAsElement(final IChromosome a_subject,
 238    final Document a_xmlDocument) {
 239    // Start by creating an element for the chromosome and its size
 240    // attribute, which represents the number of genes in the chromosome.
 241    // ------------------------------------------------------------------
 242    Element chromosomeElement =
 243    a_xmlDocument.createElement(CHROMOSOME_TAG);
 244    chromosomeElement.setAttribute(SIZE_ATTRIBUTE,
 245    Integer.toString(a_subject.size()));
 246    // Next create the genes element with its nested gene elements,
 247    // which will contain string representations of the alleles.
 248    // --------------------------------------------------------------
 249    Element genesElement = representGenesAsElement(a_subject.getGenes(),
 250    a_xmlDocument);
 251    // Add the new genes element to the chromosome element and then
 252    // return the chromosome element.
 253    // -------------------------------------------------------------
 254    chromosomeElement.appendChild(genesElement);
 255    return chromosomeElement;
 256    }
 257   
 258    /**
 259    * Marshall a Genotype instance into an XML Element representation,
 260    * including its population of Chromosome instances as sub-elements.
 261    * This may be useful in scenarios where representation as an
 262    * entire Document is undesirable, such as when the representation
 263    * of this Genotype is to be combined with other elements in a
 264    * single Document.
 265    *
 266    * @param a_subject the genotype to represent as an XML element
 267    * @param a_xmlDocument a Document instance that will be used to create
 268    * the Element instance. Note that the element will NOT be added to the
 269    * document by this method
 270    * @return an Element object representing the given Genotype
 271    *
 272    * @author Neil Rotstan
 273    * @since 1.0
 274    * @deprecated use XMLDocumentBuilder instead
 275    */
 276    public static Element representGenotypeAsElement(final Genotype a_subject,
 277    final Document a_xmlDocument) {
 278    Population population = a_subject.getPopulation();
 279    // Start by creating the genotype element and its size attribute,
 280    // which represents the number of chromosomes present in the
 281    // genotype.
 282    // --------------------------------------------------------------
 283    Element genotypeTag = a_xmlDocument.createElement(GENOTYPE_TAG);
 284    genotypeTag.setAttribute(SIZE_ATTRIBUTE,
 285    Integer.toString(population.size()));
 286    // Next, add nested elements for each of the chromosomes in the
 287    // genotype.
 288    // ------------------------------------------------------------
 289    for (int i = 0; i < population.size(); i++) {
 290    Element chromosomeElement
 291    = representChromosomeAsElement(population.getChromosome(i),
 292    a_xmlDocument);
 293    genotypeTag.appendChild(chromosomeElement);
 294    }
 295    return genotypeTag;
 296    }
 297   
 298    /**
 299    * Unmarshall a Chromosome instance from a given XML Element
 300    * representation.
 301    *
 302    * @param a_activeConfiguration current Configuration object
 303    * @param a_xmlElement the XML Element representation of the Chromosome
 304    * @return a new Chromosome instance setup with the data from the XML Element
 305    * representation
 306    *
 307    * @throws ImproperXMLException if the given Element is improperly
 308    * structured or missing data
 309    * @throws UnsupportedRepresentationException if the actively configured
 310    * Gene implementation does not support the string representation of the
 311    * alleles used in the given XML document
 312    * @throws GeneCreationException if there is a problem creating or populating
 313    * a Gene instance
 314    *
 315    * @author Neil Rotstan
 316    * @since 1.0
 317    */
 318  19 public static Gene[] getGenesFromElement(
 319    Configuration a_activeConfiguration, Element a_xmlElement)
 320    throws ImproperXMLException, UnsupportedRepresentationException,
 321    GeneCreationException {
 322    // Do some sanity checking. Make sure the XML Element isn't null and
 323    // that it in fact represents a set of genes.
 324    // -----------------------------------------------------------------
 325  19 if (a_xmlElement == null ||
 326    ! (a_xmlElement.getTagName().equals(GENES_TAG))) {
 327  1 throw new ImproperXMLException(
 328    "Unable to build Chromosome instance from XML Element: " +
 329    "given Element is not a 'genes' element.");
 330    }
 331  18 List genes = Collections.synchronizedList(new ArrayList());
 332    // Extract the nested gene elements.
 333    // ---------------------------------
 334  18 NodeList geneElements = a_xmlElement.getElementsByTagName(GENE_TAG);
 335  18 if (geneElements == null) {
 336  0 throw new ImproperXMLException(
 337    "Unable to build Gene instances from XML Element: " +
 338    "'" + GENE_TAG + "'" +
 339    " sub-elements not found.");
 340    }
 341    // For each gene, get the class attribute so we know what class
 342    // to instantiate to represent the gene instance, and then find
 343    // the child text node, which is where the string representation
 344    // of the allele is located, and extract the representation.
 345    // -------------------------------------------------------------
 346  18 int numberOfGeneNodes = geneElements.getLength();
 347  18 for (int i = 0; i < numberOfGeneNodes; i++) {
 348  101 Element thisGeneElement = (Element) geneElements.item(i);
 349  101 thisGeneElement.normalize();
 350    // Fetch the class attribute and create an instance of that
 351    // class to represent the current gene.
 352    // --------------------------------------------------------
 353  101 String geneClassName =
 354    thisGeneElement.getAttribute(CLASS_ATTRIBUTE);
 355  101 Gene thisGeneObject;
 356  101 Class geneClass = null;
 357  101 try {
 358  101 geneClass = Class.forName(geneClassName);
 359  101 try {
 360  101 Constructor constr = geneClass.getConstructor(new Class[] {
 361    Configuration.class});
 362  101 thisGeneObject = (Gene) constr.newInstance(new Object[] {
 363    a_activeConfiguration});
 364    }
 365    catch (NoSuchMethodException nsme) {
 366    // Try it by calling method newGeneInternal.
 367    // -----------------------------------------
 368  0 Constructor constr = geneClass.getConstructor(new Class[] {});
 369  0 thisGeneObject = (Gene) constr.newInstance(new Object[] {});
 370  0 thisGeneObject = (Gene) PrivateAccessor.invoke(thisGeneObject,
 371    "newGeneInternal", new Class[] {}, new Object[] {});
 372    }
 373    }
 374    catch (Throwable e) {
 375  0 throw new GeneCreationException(geneClass, e);
 376    }
 377    // Find the text node and fetch the string representation of
 378    // the allele.
 379    // ---------------------------------------------------------
 380  101 NodeList children = thisGeneElement.getChildNodes();
 381  101 int childrenSize = children.getLength();
 382  101 String alleleRepresentation = null;
 383  101 for (int j = 0; j < childrenSize; j++) {
 384  101 Element alleleElem = (Element) children.item(j);
 385  101 if (alleleElem.getTagName().equals(ALLELE_TAG)) {
 386  101 alleleRepresentation = alleleElem.getAttribute("value");
 387    }
 388  101 if (children.item(j).getNodeType() == Node.TEXT_NODE) {
 389    // We found the text node. Extract the representation.
 390    // ---------------------------------------------------
 391  0 alleleRepresentation = children.item(j).getNodeValue();
 392  0 break;
 393    }
 394    }
 395    // Sanity check: Make sure the representation isn't null.
 396    // ------------------------------------------------------
 397  101 if (alleleRepresentation == null) {
 398  0 throw new ImproperXMLException(
 399    "Unable to build Gene instance from XML Element: " +
 400    "value (allele) is missing representation.");
 401    }
 402    // Now set the value of the gene to that reflect the
 403    // string representation.
 404    // -------------------------------------------------
 405  101 try {
 406  101 thisGeneObject.setValueFromPersistentRepresentation(
 407    alleleRepresentation);
 408    }
 409    catch (UnsupportedOperationException e) {
 410  0 throw new GeneCreationException(
 411    "Unable to build Gene because it does not support the " +
 412    "setValueFromPersistentRepresentation() method.");
 413    }
 414    // Finally, add the current gene object to the list of genes.
 415    // ----------------------------------------------------------
 416  101 genes.add(thisGeneObject);
 417    }
 418  18 return (Gene[]) genes.toArray(new Gene[genes.size()]);
 419    }
 420   
 421    /**
 422    * Unmarshall a Chromosome instance from a given XML Element
 423    * representation.
 424    *
 425    * @param a_activeConfiguration the current active Configuration object
 426    * that is to be used during construction of the Chromosome
 427    * @param a_xmlElement the XML Element representation of the Chromosome
 428    * @return a new Chromosome instance setup with the data from the XML
 429    * Element representation
 430    *
 431    * @throws ImproperXMLException if the given Element is improperly
 432    * structured or missing data
 433    * @throws InvalidConfigurationException if the given Configuration is in
 434    * an inconsistent state
 435    * @throws UnsupportedRepresentationException if the actively configured
 436    * Gene implementation does not support the string representation of the
 437    * alleles used in the given XML document
 438    * @throws GeneCreationException if there is a problem creating or populating
 439    * a Gene instance
 440    *
 441    * @author Neil Rotstan
 442    * @since 1.0
 443    */
 444  17 public static Chromosome getChromosomeFromElement(
 445    Configuration a_activeConfiguration, Element a_xmlElement)
 446    throws ImproperXMLException, InvalidConfigurationException,
 447    UnsupportedRepresentationException, GeneCreationException {
 448    // Do some sanity checking. Make sure the XML Element isn't null and
 449    // that in fact represents a chromosome.
 450    // -----------------------------------------------------------------
 451  17 if (a_xmlElement == null ||
 452    ! (a_xmlElement.getTagName().equals(CHROMOSOME_TAG))) {
 453  1 throw new ImproperXMLException(
 454    "Unable to build Chromosome instance from XML Element: " +
 455    "given Element is not a 'chromosome' element.");
 456    }
 457    // Extract the nested genes element and make sure it exists.
 458    // ---------------------------------------------------------
 459  16 Element genesElement = (Element)
 460    a_xmlElement.getElementsByTagName(GENES_TAG).item(0);
 461  16 if (genesElement == null) {
 462  0 throw new ImproperXMLException(
 463    "Unable to build Chromosome instance from XML Element: " +
 464    "'genes' sub-element not found.");
 465    }
 466    // Construct the genes from their representations.
 467    // -----------------------------------------------
 468  16 Gene[] geneAlleles = getGenesFromElement(a_activeConfiguration,
 469    genesElement);
 470    // Construct the new Chromosome with the genes and return it.
 471    // ----------------------------------------------------------
 472  16 return new Chromosome(a_activeConfiguration, geneAlleles);
 473    }
 474   
 475    /**
 476    * Unmarshall a Genotype instance from a given XML Element representation.
 477    * Its population of Chromosomes will be unmarshalled from the Chromosome
 478    * sub-elements.
 479    *
 480    * @param a_activeConfiguration the current active Configuration object
 481    * that is to be used during construction of the Genotype and Chromosome
 482    * instances
 483    * @param a_xmlElement the XML Element representation of the Genotype
 484    * @return a new Genotype instance, complete with a population of Chromosomes,
 485    * setup with the data from the XML Element representation
 486    *
 487    * @throws ImproperXMLException if the given Element is improperly structured
 488    * or missing data
 489    * @throws InvalidConfigurationException if the given Configuration is in an
 490    * inconsistent state
 491    * @throws UnsupportedRepresentationException if the actively configured
 492    * Gene implementation does not support the string representation of the
 493    * alleles used in the given XML document
 494    * @throws GeneCreationException if there is a problem creating or populating
 495    * a Gene instance
 496    *
 497    * @author Neil Rotstan
 498    * @author Klaus Meffert
 499    * @since 1.0
 500    */
 501  5 public static Genotype getGenotypeFromElement(
 502    Configuration a_activeConfiguration, Element a_xmlElement)
 503    throws ImproperXMLException, InvalidConfigurationException,
 504    UnsupportedRepresentationException, GeneCreationException {
 505   
 506    // Sanity check. Make sure the XML element isn't null and that it
 507    // actually represents a genotype.
 508  5 if (a_xmlElement == null ||
 509    ! (a_xmlElement.getTagName().equals(GENOTYPE_TAG))) {
 510  1 throw new ImproperXMLException(
 511    "Unable to build Genotype instance from XML Element: " +
 512    "given Element is not a 'genotype' element.");
 513    }
 514    // Fetch all of the nested chromosome elements and convert them
 515    // into Chromosome instances.
 516    // ------------------------------------------------------------
 517  4 NodeList chromosomes =
 518    a_xmlElement.getElementsByTagName(CHROMOSOME_TAG);
 519  4 int numChromosomes = chromosomes.getLength();
 520  4 Population population = new Population(a_activeConfiguration, numChromosomes);
 521  4 for (int i = 0; i < numChromosomes; i++) {
 522  13 population.addChromosome(getChromosomeFromElement(a_activeConfiguration,
 523    (Element) chromosomes.item(i)));
 524    }
 525    // Construct a new Genotype with the chromosomes and return it.
 526    // ------------------------------------------------------------
 527  4 return new Genotype(a_activeConfiguration, population);
 528    }
 529   
 530    /**
 531    * Unmarshall a Genotype instance from a given XML Document representation.
 532    * Its population of Chromosomes will be unmarshalled from the Chromosome
 533    * sub-elements.
 534    *
 535    * @param a_activeConfiguration the current active Configuration object that
 536    * is to be used during construction of the Genotype and Chromosome instances
 537    * @param a_xmlDocument the XML Document representation of the Genotype
 538    *
 539    * @return A new Genotype instance, complete with a population of Chromosomes,
 540    * setup with the data from the XML Document representation
 541    *
 542    * @throws ImproperXMLException if the given Document is improperly structured
 543    * or missing data
 544    * @throws InvalidConfigurationException if the given Configuration is in an
 545    * inconsistent state
 546    * @throws UnsupportedRepresentationException if the actively configured Gene
 547    * implementation does not support the string representation of the alleles
 548    * used in the given XML document
 549    * @throws GeneCreationException if there is a problem creating or populating
 550    * a Gene instance
 551    *
 552    * @author Neil Rotstan
 553    * @since 1.0
 554    */
 555  4 public static Genotype getGenotypeFromDocument(
 556    Configuration a_activeConfiguration, Document a_xmlDocument)
 557    throws ImproperXMLException, InvalidConfigurationException,
 558    UnsupportedRepresentationException, GeneCreationException {
 559    // Extract the root element, which should be a genotype element.
 560    // After verifying that the root element is not null and that it
 561    // in fact is a genotype element, then convert it into a Genotype
 562    // instance.
 563    // --------------------------------------------------------------
 564  4 Element rootElement = a_xmlDocument.getDocumentElement();
 565  4 if (rootElement == null ||
 566    ! (rootElement.getTagName().equals(GENOTYPE_TAG))) {
 567  1 throw new ImproperXMLException(
 568    "Unable to build Genotype from XML Document: " +
 569    "'genotype' element must be at root of document.");
 570    }
 571  3 return getGenotypeFromElement(a_activeConfiguration, rootElement);
 572    }
 573   
 574    /**
 575    * Unmarshall a Chromosome instance from a given XML Document
 576    * representation. Its genes will be unmarshalled from the gene
 577    * sub-elements.
 578    *
 579    * @param a_activeConfiguration the current active Configuration object that
 580    * is to be used during construction of the Chromosome instances
 581    * @param a_xmlDocument the XML Document representation of the Chromosome
 582    *
 583    * @return a new Chromosome instance setup with the data from the XML Document
 584    * representation
 585    *
 586    * @throws ImproperXMLException if the given Document is improperly structured
 587    * or missing data
 588    * @throws InvalidConfigurationException if the given Configuration is in an
 589    * inconsistent state
 590    * @throws UnsupportedRepresentationException if the actively configured Gene
 591    * implementation does not support the string representation of the alleles
 592    * used in the given XML document
 593    * @throws GeneCreationException if there is a problem creating or populating
 594    * a Gene instance
 595    *
 596    * @author Neil Rotstan
 597    * @since 1.0
 598    */
 599  3 public static Chromosome getChromosomeFromDocument(Configuration
 600    a_activeConfiguration, Document a_xmlDocument)
 601    throws ImproperXMLException, InvalidConfigurationException,
 602    UnsupportedRepresentationException, GeneCreationException {
 603    // Extract the root element, which should be a chromosome element.
 604    // After verifying that the root element is not null and that it
 605    // in fact is a chromosome element, then convert it into a Chromosome
 606    // instance.
 607    // ------------------------------------------------------------------
 608  3 Element rootElement = a_xmlDocument.getDocumentElement();
 609  2 if (rootElement == null ||
 610    ! (rootElement.getTagName().equals(CHROMOSOME_TAG))) {
 611  0 throw new ImproperXMLException(
 612    "Unable to build Chromosome instance from XML Document: " +
 613    "'chromosome' element must be at root of Document.");
 614    }
 615  2 return getChromosomeFromElement(a_activeConfiguration, rootElement);
 616    }
 617   
 618    /**
 619    * Reads in an XML file and returns a Document object
 620    * @param file the file to be read in
 621    * @throws IOException
 622    * @throws SAXException
 623    * @return Document
 624    *
 625    * @author Klaus Meffert
 626    * @since 2.0
 627    */
 628  2 public static Document readFile(File file)
 629    throws IOException, org.xml.sax.SAXException {
 630  2 return m_documentCreator.parse(file);
 631    }
 632   
 633    /**
 634    * Writes an XML file from a Document object
 635    * @param doc the Document object to be written to file
 636    * @param file the file to be written
 637    * @throws IOException
 638    *
 639    * @author Klaus Meffert
 640    * @since 2.0
 641    */
 642  3 public static void writeFile(Document doc, File file)
 643    throws IOException {
 644    // Use a Transformer for output
 645  3 TransformerFactory tFactory =
 646    TransformerFactory.newInstance();
 647  3 Transformer transformer;
 648  3 try {
 649  3 transformer = tFactory.newTransformer();
 650    }
 651    catch (TransformerConfigurationException tex) {
 652  0 throw new IOException(tex.getMessage());
 653    }
 654  3 DOMSource source = new DOMSource(doc);
 655  3 FileOutputStream fos = new FileOutputStream(file);
 656  3 StreamResult result = new StreamResult(fos);
 657  3 try {
 658  3 transformer.transform(source, result);
 659  3 fos.close();
 660    }
 661    catch (TransformerException tex) {
 662  0 throw new IOException(tex.getMessage());
 663    }
 664    }
 665    }