/*
* This file is part of JGAP.
*
* JGAP offers a dual license model containing the LGPL as well as the MPL.
*
* For licensing information please see the file license.txt included with JGAP
* or have a look at the top of class org.jgap.Chromosome which representatively
* includes the JGAP license policy applicable for any file delivered with JGAP.
*/
package org.jgap.data;
import org.jgap.*;
/**
* Builds a tree structure from Genes, Chrosomes or from a Genotype.
* <p>
* Generated result is generic data type usable for concrete persistence
* strategies, including XML documents, writing an object to a file or
* stream etc.
*
* @author Klaus Meffert
* @since 2.0
*/
public class DataTreeBuilder {
/**@todo implement representGPGenotype..*/
/** String containing the CVS revision. Read out via reflection!*/
private final static String CVS_REVISION = "$Revision: 1.12 $";
/**
* Constant representing the name of the genotype element tag.
*/
private static final String GENOTYPE_TAG = "genotype";
/**
* Constant representing the name of the chromosome element tag.
*/
private static final String CHROMOSOME_TAG = "chromosome";
/**
* Constant representing the name of the gene element tag.
*/
private static final String GENES_TAG = "genes";
/**
* Constant representing the name of the gene element tag.
*/
private static final String GENE_TAG = "gene";
private static final String ALLELE_TAG = "allele";
/**
* Constant representing the name of the size attribute that is
* added to genotype and chromosome elements to describe their size.
*/
private static final String SIZE_ATTRIBUTE = "size";
/**
* Constant representing the fully-qualified name of the concrete
* Gene class that was marshalled.
*/
private static final String CLASS_ATTRIBUTE = "class";
/**
* Shared lock object used for synchronization purposes.
*/
private Object m_lock;
private static DataTreeBuilder m_instance;
/**
* @return the singleton instance of this class
*
* @author Klaus Meffert
* @since 2.0
*/
public static synchronized DataTreeBuilder getInstance() {
if (m_instance == null) {
m_instance = new DataTreeBuilder();
m_instance.m_lock = new Object();
}
return m_instance;
}
/**
* Private constructor for Singleton
*/
private DataTreeBuilder() {
}
/**
* Represent a Genotype as a generic data document, including its
* population of Chromosome instances.
*
* @param a_subject the genotype to represent
* @throws Exception
* @return a generic document object representing the given Genotype
*
* @author Klaus Meffert
* @since 2.0
*/
public IDataCreators representGenotypeAsDocument(final Genotype a_subject)
throws Exception {
// DocumentBuilders do not have to be thread safe, so we have to
// protect creation of the Document with a synchronized block.
// -------------------------------------------------------------
IDataCreators genotypeDocument;
synchronized (m_lock) {
genotypeDocument = new DataElementsDocument();
genotypeDocument.setTree(createTree());
}
IDataElement genotypeElement = representGenotypeAsElement(a_subject);
genotypeDocument.appendChild(genotypeElement);
return genotypeDocument;
}
/**
* Represent a Genotype as a generic data element, including its
* population of Chromosome instances.
*
* This may be useful in scenarios where representation as an entire document
* is undesirable, such as when the representation of this Genotype is to be
* combined with other elements in a single document.
*
* @param a_subject the genotype to represent
* @throws Exception
* @return an element object representing the given Genotype
*
* @author Klaus Meffert
* @since 2.0
*/
public IDataElement representGenotypeAsElement(final Genotype a_subject)
throws Exception {
Population population = a_subject.getPopulation();
// Start by creating the genotype element and its size attribute,
// which represents the number of chromosomes present in the
// genotype.
// --------------------------------------------------------------
IDataElement genotypeTag = new DataElement(GENOTYPE_TAG);
genotypeTag.setAttribute(SIZE_ATTRIBUTE,
Integer.toString(population.size()));
// Next, add nested elements for each of the chromosomes in the
// genotype.
// ------------------------------------------------------------
for (int i = 0; i < population.size(); i++) {
IDataElement chromosomeElement =
representChromosomeAsElement(population.getChromosome(i));
genotypeTag.appendChild(chromosomeElement);
}
return genotypeTag;
}
/**
* Represent a Chromosome as a generic data type document, including its
* contained Gene instances.
*
* @param a_subject the chromosome to represent
* @throws Exception
* @return a document object representing the given Chromosome
*
* @author Klaus Meffert
* @since 2.0
*/
public IDataCreators representChromosomeAsDocument(final IChromosome a_subject)
throws Exception {
// DocumentBuilders do not have to be thread safe, so we have to
// protect creation of the Document with a synchronized block.
// -------------------------------------------------------------
IDataCreators chromosomeDocument;
synchronized (m_lock) {
// Build data structure for tree
chromosomeDocument = new DataElementsDocument();
chromosomeDocument.setTree(createTree());
}
IDataElement chromosomeElement =
representChromosomeAsElement(a_subject);
chromosomeDocument.appendChild(chromosomeElement);
return chromosomeDocument;
}
protected IDataElementList createTree() {
return new DataElementList();
}
/**
* Represent a Chromosome as a generic data element, including its
* contained Gene instances.
* This may be useful in scenarios where representation as an entire document
* is undesirable, such as when the representation of this Chromosome is to
* be combined with other elements in a single document.
*
* @param a_subject the chromosome to represent
* @throws Exception
* @return an element object representing the given Chromosome
*
* @author Klaus Meffert
* @since 2.0
*/
public IDataElement representChromosomeAsElement(final IChromosome a_subject)
throws Exception {
// Start by creating an element for the chromosome and its size
// attribute, which represents the number of genes in the chromosome.
// ------------------------------------------------------------------
IDataElement chromosomeElement = new DataElement(CHROMOSOME_TAG);
chromosomeElement.setAttribute(SIZE_ATTRIBUTE,
Integer.toString(a_subject.size()));
// Next create the genes element with its nested gene elements,
// which will contain string representations of the alleles.
// --------------------------------------------------------------
IDataElement genesElement = representGenesAsElement(a_subject.getGenes());
// Add the new genes element to the chromosome element and then
// Add the new genes element to the chromosome element and then
// return the chromosome element.
// -------------------------------------------------------------
chromosomeElement.appendChild(genesElement);
return chromosomeElement;
}
/**
* Represent Genes as a generic data type element.
*
* @param a_geneValues the genes to represent
* @throws Exception
* @return an element object representing the given genes
*
* @author Klaus Meffert
* @since 2.0
*/
public IDataElement representGenesAsElement(final Gene[] a_geneValues)
throws Exception {
// Create the parent genes element.
// --------------------------------
IDataElement genesElement = new DataElement(GENES_TAG);
// Now add gene sub-elements for each gene in the given array.
// ---------------------------------------------------------------
IDataElement geneElement;
for (int i = 0; i < a_geneValues.length; i++) {
geneElement = representGeneAsElement(a_geneValues[i]);
genesElement.appendChild(geneElement);
}
return genesElement;
}
/**
* Represent a Gene as a generic data element.
*
* @param a_gene the Gene to represent
* @throws Exception
* @return an element object representing the given gene
*
* @author Klaus Meffert
* @since 2.0
*/
public IDataElement representGeneAsElement(final Gene a_gene)
throws Exception {
// Create the allele element for this gene.
// ----------------------------------------
IDataElement geneElement = new DataElement(GENE_TAG);
// Add the class attribute and set its value to the class
// name of the concrete class representing the current Gene.
// ---------------------------------------------------------
geneElement.setAttribute(CLASS_ATTRIBUTE,
a_gene.getClass().getName());
// Create a text node to contain the string representation of
// the gene's value (allele).
// ----------------------------------------------------------
geneElement.appendChild(representAlleleAsElement(a_gene));
return geneElement;
}
/**
* Represent an Allele as a generic data element
*
* @param a_gene the gene holding the allele
* @throws Exception
* @return IDataElement created data element
*
* @author Klaus Meffert
* @since 2.0
*/
private IDataElement representAlleleAsElement(final Gene a_gene)
throws Exception {
IDataElement alleleElement = new DataElement(ALLELE_TAG);
alleleElement.setAttribute("value", a_gene.getPersistentRepresentation());
return alleleElement;
}
}