package org.genedb.db.domain.test;
import org.genedb.db.domain.objects.BasicGene;
import org.genedb.db.domain.objects.Chromosome;
import org.genedb.db.domain.objects.Exon;
import org.genedb.db.domain.objects.Gap;
import org.genedb.db.domain.objects.Transcript;
import org.genedb.db.domain.objects.TranscriptComponent;
import org.genedb.db.domain.services.BasicGeneService;
import org.genedb.util.TwoKeyMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
/**
* Used to generate BasicGene objects for testing.
* Ordinarily used via the proxy methods of {@link MockBasicGeneService}
* rather than directly.
*
* @author rh11
*
*/
class BasicGeneFactory {
private int nextId;
private String organism;
private Chromosome chromosome;
private int strand;
/**
* The default length of a test chromosome, if not explicitly specified.
*/
private static int DEFAULT_CHR_LENGTH = 1000000;
private static int DEFAULT_CHR_ID = 101;
/**
* Sets the default organism, chromosome and strand for genes produced by this factory.
*
* @param organism
* @param chromosome
* @param strand
*/
public BasicGeneFactory(String organism, String chromosome, int strand) {
assert strand == 1 || strand == -1;
this.nextId = 1;
this.organism = organism;
this.chromosome = new Chromosome(chromosome, DEFAULT_CHR_ID, DEFAULT_CHR_LENGTH);
this.strand = strand;
}
/**
* Create a BasicGene with the specified uniqueName and location,
* on the strand and chromosome specified by this factory. A gene created
* by this method will have no transcripts. Transcripts must be added
* manually, perhaps using {@link BasicGeneHelper}.
*
* @param uniqueName
* @param fmin
* @param fmax
* @return
*/
public BasicGene nakedGene (String uniqueName, int fmin, int fmax) {
BasicGene gene = new BasicGene();
gene.setFeatureId(nextId++);
gene.setOrganism(organism);
gene.setChromosome(chromosome);
gene.setStrand(strand);
gene.setUniqueName(uniqueName);
gene.setFmin(fmin);
gene.setFmax(fmax);
return gene;
}
/**
* Create a new BasicGene with the specified uniqueName and location,
* on the strand and chromosome specified by this factory. A gene created
* by this method will have one transcript, consisting of one exon.
*
* @param uniqueName
* @param fmin
* @param fmax
* @return
*/
public BasicGene simpleGene (String uniqueName, int fmin, int fmax, Integer colourId) {
BasicGene gene = nakedGene(uniqueName, fmin, fmax);
// Produce a single transcript for this gene
Transcript transcript = new Transcript();
transcript.setFmin(fmin);
transcript.setFmax(fmax);
transcript.setColourId(colourId);
// with a single exon
Set<TranscriptComponent> exons = new HashSet<TranscriptComponent> ();
exons.add(new Exon(fmin, fmax));
transcript.setComponents(exons);
gene.addTranscript(transcript);
return gene;
}
/**
* Create a new BasicGene with the specified uniqueName, name and location,
* on the strand and chromosome specified by this factory.
*
* @param uniqueName
* @param fmin
* @param fmax
* @return
*/
public BasicGene simpleGene (String uniqueName, String name, int fmin, int fmax, Integer colourId) {
BasicGene gene = simpleGene(uniqueName, fmin, fmax, colourId);
gene.setName(name);
return gene;
}
/**
* Change the default organism for genes produced by this factory.
*
*
* @param organism The name of the new default organism
*/
public void setOrganism(String organism) {
this.organism = organism;
}
/**
* Change the default chromosome for genes produced by this factory.
*
* @param chromosome The new default chromosome
*/
public void setChromosome(Chromosome chromosome) {
this.chromosome = chromosome;
}
/**
* Change the default chromosome for genes produced by this factory.
* This convenience method creates a new {@link org.genedb.db.domain.objects.Chromosome}
* object with a default length.
*
* @param chromosome The name of the new default chromosome
*/
public void setChromosome(String chromosomeName) {
this.chromosome = new Chromosome(chromosomeName, DEFAULT_CHR_ID, DEFAULT_CHR_LENGTH);
}
/**
* Change the default strand for genes produced by this factory.
*
* @param strand The new default strand (<code>1</code> or <code>-1</code>)
*/
public void setStrand(int strand) {
assert strand == 1 || strand == -1;
this.strand = strand;
}
public String getOrganism() {
return organism;
}
public String getChromosomeName() {
return chromosome.getName();
}
}
/**
* A stub class that implements the {@link org.genedb.db.domain.services.BasicGeneService} interface
* using sample data. A new instance initially contains no genes; genes can be added using the methods
* {@link #addSimpleGene(String,int,int,Integer)}, {@link #addSimpleGene(String,String,int,int,Integer)}
* etc.
*
* @author rh11
*
*/
public class MockBasicGeneService implements BasicGeneService {
private BasicGeneFactory factory;
private Collection<BasicGene> genes;
private TwoKeyMap<String,String,Collection<Gap>> gapsByOrganismAndChromosome;
/**
* Creates a new instance that uses the supplied organism, chromosome and strand
* as the default for genes that are added using the <code>add*Gene</code> methods.
*
* These defaults can be changed with the <code>set*</code> methods, which change
* the values used for genes added subsequently.
*
* @param organism
* @param chromosome
* @param strand
*/
public MockBasicGeneService (String organism, String chromosome, int strand) {
factory = new BasicGeneFactory(organism, chromosome, strand);
genes = new ArrayList<BasicGene> ();
gapsByOrganismAndChromosome = new TwoKeyMap<String,String,Collection<Gap>>();
}
/**
* Add a simple, minimal gene.
*
* @param uniqueName
* @param fmin
* @param fmax
*/
public void addSimpleGene(String uniqueName, int fmin, int fmax) {
genes.add(factory.simpleGene(uniqueName, fmin, fmax, null));
}
/**
* Add a simple Gene.
* This method is a proxy for {@see BasicGeneFactory.addSimpleGene(String,int,int,Integer)}.
*
* @param uniqueName
* @param fmin
* @param fmax
* @param colourId
*/
public void addSimpleGene(String uniqueName, int fmin, int fmax, Integer colourId) {
genes.add(factory.simpleGene(uniqueName, fmin, fmax, colourId));
}
/**
* Add a simple Gene with a name and a colour.
* This method is a proxy for {@see BasicGeneFactory.addSimpleGene(String,int,int,Integer)}.
*
* @param uniqueName
* @param name
* @param fmin
* @param fmax
* @param colourId
*/
public void addSimpleGene(String uniqueName, String name, int fmin, int fmax, Integer colourId) {
genes.add(factory.simpleGene(uniqueName, name, fmin, fmax, colourId));
}
/**
* Add a gene with no transcripts. This is used to generate alternatively-spliced
* test genes in conjunction with {@link BasicGeneHelper#transcript(String,int,int)}.
*
* For example,
* <code>
* mockBasicGeneService.addAltGene("gene1", 100, 200)
* .transcript("rna1", 100, 150)
* .transcript("rna2", 120, 200);
* </code>
*
* @param uniqueName
* @param fmin
* @param fmax
* @return
*/
public BasicGeneHelper addAltGene(String uniqueName, int fmin, int fmax) {
BasicGeneHelper gene = new BasicGeneHelper(factory.nakedGene(uniqueName, fmin, fmax));
genes.add(gene);
return gene;
}
/**
* Add a gap.
*
* @param uniqueName
* @param fmin
* @param fmax
*/
public void addGap(String uniqueName, int fmin, int fmax) {
String organism = factory.getOrganism();
String chromosome = factory.getChromosomeName();
if (!gapsByOrganismAndChromosome.containsKey(organism,chromosome)) {
gapsByOrganismAndChromosome.put(organism, chromosome, new TreeSet<Gap>());
}
gapsByOrganismAndChromosome.get(organism,chromosome).add(new Gap(uniqueName, fmin, fmax));
}
/**
* Get all the gaps for the specified chromosome of the specified organism.
*
* @param organism the common name of the organism
* @param chromosome the unique name of the chromosome
* @return
*/
public Collection<Gap> findGapsOnChromosome(String organism, String chromosome) {
if (!gapsByOrganismAndChromosome.containsKey(organism, chromosome))
return Collections.emptySet();
return gapsByOrganismAndChromosome.get(organism, chromosome);
}
/**
* Change the default organism used for new genes.
* This method is a proxy for {@see BasicGeneFactory.setOrganism(String)}.
*
* @param organism
*/
public void setOrganism(String organism) {
factory.setOrganism(organism);
}
/**
* Change the default chromosome used for new genes.
* This method is a proxy for {@see BasicGeneFactory.setChromosome(String)}.
*
* @param chromosome
*/
public void setChromosome(String chromosome) {
factory.setChromosome(chromosome);
}
/**
* Change the default chromosome used for new genes.
* This method is a proxy for {@see BasicGeneFactory.setChromosome(Chromosome)}.
*
* @param chromosome
*/
public void setChromosome(Chromosome chromosome) {
factory.setChromosome(chromosome);
}
/**
* Change the default strand used for new genes.
* This method is a proxy for {@see BasicGeneFactory.setStrand(int)}.
*
* @param strand
*/
public void setStrand(int strand) {
factory.setStrand(strand);
}
public BasicGene findGeneByUniqueName(String name) {
for (BasicGene gene: genes) {
if (gene.getUniqueName().equals(name))
return gene;
}
return null;
}
public List<String> findGeneNamesByPartialName(String search) {
throw new RuntimeException("Did not expect ContextMapDiagram to call findGeneNamesByPartialName");
}
public Collection<BasicGene> findGenesOverlappingRange(String organism,
String chromosome, int strand, long locMin, long locMax) {
List<BasicGene> ret = new ArrayList<BasicGene> ();
for (BasicGene gene: genes) {
if (gene.getOrganism().equals(organism)
&& gene.getChromosomeName().equals(chromosome)
&& gene.getStrand() == strand
&& gene.getFmin() < locMax
&& gene.getFmax() >= locMin)
ret.add(gene);
}
return ret;
}
public Collection<BasicGene> findGenesOnStrand(String organism,
String chromosome, int strand) {
List<BasicGene> ret = new ArrayList<BasicGene> ();
for (BasicGene gene: genes) {
if (gene.getOrganism().equals(organism)
&& gene.getChromosomeName().equals(chromosome)
&& gene.getStrand() == strand)
ret.add(gene);
}
return ret;
}
public Collection<BasicGene> findGenesExtendingIntoRange(String organism,
String chromosome, int strand, long locMin, long locMax) {
List<BasicGene> ret = new ArrayList<BasicGene> ();
for (BasicGene gene: genes) {
if (gene.getOrganism().equals(organism)
&& gene.getChromosomeName().equals(chromosome)
&& gene.getStrand() == strand
&& gene.getFmax() < locMax
&& gene.getFmax() >= locMin)
ret.add(gene);
}
return ret;
}
public Collection<Gap> findGapsOverlappingRange(String organismCommonName,
String chromosomeUniqueName, long locMin, long locMax) {
List<Gap> ret = new ArrayList<Gap> ();
for (Gap gap: findGapsOnChromosome(organismCommonName, chromosomeUniqueName)) {
if (gap.getFmin() < locMax
&& gap.getFmax() >= locMin)
ret.add(gap);
}
return ret;
}
}