001/**
002 * Copyright (C) 2010-2015 The Roslin Institute <contact andy.law@roslin.ed.ac.uk>
003 *
004 * This file is part of JEnsembl: a Java API to Ensembl data sources developed by the
005 * Bioinformatics Group at The Roslin Institute, The Royal (Dick) School of
006 * Veterinary Studies, University of Edinburgh.
007 *
008 * Project hosted at: http://jensembl.sourceforge.net
009 *
010 * This is free software: you can redistribute it and/or modify
011 * it under the terms of the GNU General Public License (version 3) as published by
012 * the Free Software Foundation.
013 *
014 * This software is distributed in the hope that it will be useful,
015 * but WITHOUT ANY WARRANTY; without even the implied warranty of
016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
017 * GNU General Public License for more details.
018 *
019 * You should have received a copy of the GNU General Public License
020 * in this software distribution. If not, see: http://opensource.org/licenses/gpl-3.0.html
021 */
022package uk.ac.roslin.ensembl.dao.database;
023
024import java.util.*;
025import uk.ac.roslin.ensembl.config.EnsemblComparaDivision;
026import uk.ac.roslin.ensembl.config.EnsemblDBType;
027import uk.ac.roslin.ensembl.datasourceaware.core.*;
028import uk.ac.roslin.ensembl.exception.DAOException;
029import uk.ac.roslin.ensembl.model.core.Species;
030import uk.ac.roslin.ensembl.model.database.*;
031
032public class DBSpecies implements Species {
033
034    protected String databaseStyleSpeciesName = "";
035    // note this could now be a trinomial from Ensembl 66
036    protected String speciesBinomial = "";
037    protected String commonName = "";
038//    protected String comparaName = "";
039    protected String shortName = "";
040    protected String urlName = "";
041    //these are both taken from the config file
042    protected String mostRecentEnsemblSchemaVersion = "";
043//    protected String mostRecentDBRelease = "";
044    //this is determined from parsing the databases found
045    protected Integer highestDBRelease = 0;
046    protected String taxonomyID = "";
047    protected String ensemblStablePrefix = "";
048    protected TreeSet<String> aliases = new TreeSet<String>();
049    protected Registry registry = null;
050    private TreeSet<DBSingleSpeciesDatabase> databases = new TreeSet<DBSingleSpeciesDatabase>();
051    private DBSingleSpeciesCoreDatabase mostRecentCoreDatabase;
052    private final Integer dBSpeciesID = 1;
053    //this acts as the chromosome cache, hashed by version then by name
054    protected TreeMap<String, TreeMap<String, DAChromosome>> chromosomes =
055            new TreeMap<String, TreeMap<String, DAChromosome>>(); 
056    protected TreeSet<String> allChromosomesRetrieved = new TreeSet<String>();
057    //this acts as the fragment cache for species without chromosomes (i.e. top level assembled sequences), 
058    //hashed by version then by name
059    protected TreeMap<String, TreeMap<String, DAAssembledDNASequence>> fragments =
060            new TreeMap<String, TreeMap<String, DAAssembledDNASequence>>();
061    protected TreeSet<String> allFragmentsRetrieved = new TreeSet<String>();
062    protected TreeSet<String> dbVersions = new TreeSet<String>();
063    protected TreeSet<String> schemaVersions = new TreeSet<String>();
064    EnsemblDBType dbType;
065    //default value
066    EnsemblComparaDivision comparaDivision = EnsemblComparaDivision.MULTI;
067    
068//    HashMap<String, HashMap<DAChromosome,MappingSet>> assemblyExceptions = 
069//            new HashMap<String, HashMap<DAChromosome,MappingSet>>();
070    
071    protected HashMap<String, String> assemblyAccessionsByVersion = new HashMap<String, String>();
072    protected HashMap<String, String> assemblyNamesByVersion = new HashMap<String, String>();
073    protected HashMap<String, String> comparaNameByVersion = new HashMap<String, String>();
074    protected HashMap<Integer, String> dbStyleNameByVersion = new HashMap<Integer, String>();
075    
076
077    public DBSpecies() {
078        dbType = EnsemblDBType.core;
079    }
080
081    public DBSpecies(DBSingleSpeciesCoreDatabase database) {
082        this();
083        this.registry = database.getRegistry();
084        mostRecentEnsemblSchemaVersion = registry.getMostRecentEnsemblVersion();
085        
086        this.addDatabase(database);
087
088//        //from dbVersion 59 releases, the meta table holds the species.production_name,
089//        //species.short_name and species.scientific_name meta_keys
090//        //making this obsolete - but we will need to perform it in DBDatabaseDAO if
091//        //it is a pre59 release
092//        databaseStyleSpeciesName=this.currentCoreDatabase.getDbSpeciesName();
093//        speciesBinomial = databaseStyleSpeciesName.replaceFirst( databaseStyleSpeciesName.substring(0, 1), (databaseStyleSpeciesName.substring(0,1)).toUpperCase() ).replace("_"," ");
094//        aliases.add(speciesBinomial);
095
096    }
097
098    @Override
099    public TreeSet<String> getAliases() {
100        return aliases;
101    }
102
103    //will be overridden in DBCollectionSpecies
104    @Override
105    public void setProperty(HashMap row) {
106
107        String key = (String) row.get("key");
108        String value = (String) row.get("value");
109
110        //making aliases all lower case now
111        if (key.startsWith("species.")
112                 && ! key.equals("species.division")
113                    && ! key.equals("species.stable_id_prefix")) {
114            aliases.add(value.toLowerCase());
115        }
116        
117        if (key.equals("species.stable_id_prefix")) {
118            this.ensemblStablePrefix = value;
119        } else if (key.equals("species.common_name")
120                || key.equals("species.ensembl_common_name")) {
121            this.commonName = value;
122        } else if (key.equals("species.short_name")
123                || key.equals("species.display_name")) {
124            this.shortName = value;
125        } else if (key.equals("species.scientific_name")) {
126            this.speciesBinomial = value;
127        } else if (key.equals("species.production_name")) {
128            this.databaseStyleSpeciesName = value;
129        } else if (key.equals("species.taxonomy_id")) {
130            this.taxonomyID = value;
131        } else if (key.equals("species.url")) {
132            this.urlName = value;
133        } 
134    }
135
136    @Override
137    public CoreDatabase getMostRecentCoreDatabase() {
138        return mostRecentCoreDatabase;
139    }
140
141    @Override
142    public String getCommonName() {
143        return commonName;
144    }
145
146    @Override
147    public String getShortName() {
148        return shortName;
149    }
150    
151    @Override
152    public String getDisplayName() {
153        return shortName;
154    }
155
156    public void setShortName(String name) {
157        shortName = name;
158    }
159
160    @Override
161    public String getDatabaseStyleName() {
162        return databaseStyleSpeciesName;
163    }
164
165    @Override
166    public TreeSet<? extends DBDatabase> getDatabases() {
167        return databases;
168    }
169
170    @Override
171    public void addDatabases(TreeSet<? extends Database> databases) {
172        for (Database d : databases) {
173            this.addDatabase(d);
174        }
175    }
176
177    @Override
178    public void addDatabase(Database database) {
179
180        try {
181            this.databases.add((DBSingleSpeciesDatabase) database);
182            
183            if (database.getType().equals(dbType)) {
184                this.dbVersions.add(database.getDBVersion());
185                this.schemaVersions.add(database.getSchemaVersion());
186                //check that we are not adding a more recent release than we know about
187                if (database.getIntDBVersion() > this.highestDBRelease) {
188                    this.highestDBRelease = database.getIntDBVersion();
189                    this.mostRecentCoreDatabase = (DBSingleSpeciesCoreDatabase) database;
190                }               
191            }
192        } catch (Exception e) {
193        }
194
195    }
196
197    @Override
198    public String getEnsemblStablePrefix() {
199        return ensemblStablePrefix;
200    }
201
202    @Override
203    public String getSpeciesBinomial() {
204        return speciesBinomial;
205    }
206
207    @Override
208    public String getTaxonomyID() {
209        return taxonomyID;
210    }
211
212    @Override
213    public TreeSet<? extends DBDatabase> getDatabasesByType(DatabaseType type) {
214        TreeSet<DBSingleSpeciesDatabase> out = new TreeSet<DBSingleSpeciesDatabase>();
215        for (DBDatabase d : databases) {
216            if (d instanceof DBSingleSpeciesDatabase && d.getType() == type) {
217                out.add((DBSingleSpeciesDatabase) d);
218            }
219        }
220        return out;
221    }
222
223    @Override
224    public TreeSet<? extends DBDatabase> getDatabasesByVersion(String version) {
225        TreeSet<DBSingleSpeciesDatabase> out = new TreeSet<DBSingleSpeciesDatabase>();
226        for (DBDatabase d : databases) {
227            if (d instanceof DBSingleSpeciesDatabase && d.getDBVersion().equals(version)) {
228                out.add((DBSingleSpeciesDatabase) d);
229            }
230        }
231        return out;
232    }
233
234    @Override
235    public DBDatabase getDatabaseByTypeAndVersion(DatabaseType type, String version) {
236
237        for (DBDatabase d : databases) {
238            if (d.getDBVersion().equalsIgnoreCase(version) && d.getType() == type) {
239                return d;
240            }
241        }
242        return null;
243    }
244
245    public void setCommonName(String commonName) {
246        this.commonName = commonName;
247    }
248
249    public void setEnsemblStablePrefix(String ensemblStablePrefix) {
250        this.ensemblStablePrefix = ensemblStablePrefix;
251    }
252
253    public void setSpeciesBinomial(String speciesBinomial) {
254        this.speciesBinomial = speciesBinomial;
255    }
256
257    public void setTaxonomyID(String taxonomyID) {
258        this.taxonomyID = taxonomyID;
259    }
260
261    @Override
262    public Integer getDBSpeciesID(String version) {
263        return this.dBSpeciesID;
264    }
265
266    public Integer getDBSpeciesID() {
267        return this.dBSpeciesID;
268    }
269
270    @Override
271    public String getComparaName(String version) {
272        // only the current most recent database species has this parsed and set on registry init()
273        //all other dbVersions need a lazy load of metadata
274       if (this.comparaNameByVersion.get(version) == null 
275               && this.getDatabaseByTypeAndVersion(EnsemblDBType.core, version) != null ) {
276           //trigger lazyload of metadata
277           this.setComparaName(version, ((SingleSpeciesCoreDatabase)this.getDatabaseByTypeAndVersion(dbType, version)).getComparaName());
278       }
279       return   (this.comparaNameByVersion.get(version)==null)?"":this.comparaNameByVersion.get(version);
280    }
281   
282    public void setComparaName(String version, String comparaName) {
283        this.comparaNameByVersion.put(version, comparaName);
284    }
285
286    @Override
287    public TreeMap<String, DAChromosome> getChromosomes() throws DAOException {
288        return getChromosomes(null);
289    }
290
291    @Override
292    public TreeMap<String, DAChromosome> getChromosomes(String dbVersion) throws DAOException {
293
294        if (dbVersion == null || dbVersion.isEmpty()) {
295            dbVersion = highestDBRelease.toString();
296        }
297
298        if (!this.getDBVersions().contains(dbVersion)) {
299            throw new DAOException("No version " + dbVersion + " for " + this.toString());
300        }
301
302        if (this.allChromosomesRetrieved.contains(dbVersion)) {
303            return this.chromosomes.get(dbVersion);
304        }
305
306        List<DAChromosome> chrs = null;
307
308        chrs = ((DBSingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(EnsemblDBType.core, dbVersion)).getChromosomes();
309        this.allChromosomesRetrieved.add(dbVersion);
310        this.cacheChromosomes(dbVersion, chrs);
311
312        return this.chromosomes.get(dbVersion);
313    }
314    
315    @Override
316    public TreeMap<String, DAAssembledDNASequence> getFragments() throws DAOException {
317        return getFragments(null);
318    }    
319    
320    @Override
321    public TreeMap<String, DAAssembledDNASequence> getFragments(String dbVersion) throws DAOException {
322
323//        TreeMap<String, DAAssembledDNASequence> out = new TreeMap<String, DAAssembledDNASequence>();
324//        //note we are not caching these like we do for the chromosomes...
325        
326        if (dbVersion == null || dbVersion.isEmpty()) {
327            dbVersion = highestDBRelease.toString();
328        }
329
330        if (!this.getDBVersions().contains(dbVersion)) {
331            throw new DAOException("No version " + dbVersion + " for " + this.toString());
332        }
333
334        if (this.allFragmentsRetrieved.contains(dbVersion)) {
335            return this.fragments.get(dbVersion);
336        }
337        
338        List<DAAssembledDNASequence> ass = null;
339
340        ass = ((DBSingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(EnsemblDBType.core, dbVersion)).getFragments();
341
342        this.allFragmentsRetrieved.add(dbVersion);
343        
344        this.cacheFragments(dbVersion, ass);
345
346        return this.fragments.get(dbVersion);
347    }
348
349    private void cacheChromosomes(String dbVersion, Collection<DAChromosome> chrs) {
350
351        if (dbVersion != null && !dbVersion.isEmpty()) {
352            if (!this.chromosomes.containsKey(dbVersion)) {
353                this.chromosomes.put(dbVersion, new TreeMap<String, DAChromosome>());
354            }
355            if (chrs != null) {
356                for (DAChromosome c : chrs) {
357                    if (!chromosomes.get(dbVersion).containsKey(c.getChromosomeName())) {
358                        chromosomes.get(dbVersion).put(c.getChromosomeName(), c);
359                    }
360                }
361            }
362        }
363    }
364    
365    private void cacheFragments(String dbVersion, Collection<DAAssembledDNASequence> ass) {
366
367        if (dbVersion != null && !dbVersion.isEmpty()) {
368            if (!this.fragments.containsKey(dbVersion)) {
369                this.fragments.put(dbVersion, new TreeMap<String, DAAssembledDNASequence>());
370            }
371            if (ass != null) {
372                for (DAAssembledDNASequence a : ass) {
373                    if (!fragments.get(dbVersion).containsKey(a.getName())) {
374                        fragments.get(dbVersion).put(a.getName(), a);
375                    }
376                }
377            }
378        }
379    }
380       
381    private void cacheChromosome(String dbVersion, DAChromosome chr) {
382
383        if (dbVersion != null && !dbVersion.isEmpty() && chr != null) {
384            if (!this.chromosomes.containsKey(dbVersion)) {
385                this.chromosomes.put(dbVersion, new TreeMap<String, DAChromosome>());
386            }
387            if (!chromosomes.get(dbVersion).containsKey(chr.getChromosomeName())) {
388                chromosomes.get(dbVersion).put(chr.getChromosomeName(), chr);
389            }
390        }
391    }
392    
393    private void cacheFragment(String dbVersion, DAAssembledDNASequence ass) {
394
395        if (dbVersion != null && !dbVersion.isEmpty() && ass != null) {
396            if (!this.fragments.containsKey(dbVersion)) {
397                this.fragments.put(dbVersion, new TreeMap<String, DAAssembledDNASequence>());
398            }
399            if (!fragments.get(dbVersion).containsKey(ass.getName())) {
400                fragments.get(dbVersion).put(ass.getName(), ass);
401            }
402        }
403    }
404
405    @Override
406    public DAChromosome getChromosomeByName(String name) throws DAOException {
407        return this.getChromosomeByName(name, null);
408    }
409    
410    @Override
411    public DAAssembledDNASequence getFragmentByName(String name) throws DAOException {
412        return this.getFragmentByName(name, null);
413    }
414
415    @Override
416    public DAChromosome getChromosomeByName(String name, String dbVersion) throws DAOException {
417        DAChromosome chr = null;
418
419        if (name==null || name.isEmpty()) {
420            return null;
421        }
422
423        if (dbVersion == null || dbVersion.isEmpty()) {
424            if (this.highestDBRelease!=null && this.highestDBRelease!=0) {
425                 dbVersion = this.highestDBRelease.toString();  
426            } else {
427                return null;
428            }
429        }
430
431        if (!this.getDBVersions().contains(dbVersion)) {
432            throw new DAOException("No version " + dbVersion + " for " + this.toString());
433        }
434
435        if (this.chromosomes.containsKey(dbVersion) && this.chromosomes.get(dbVersion).containsKey(name)) {
436            return this.chromosomes.get(dbVersion).get(name);
437        } else  if (this.allChromosomesRetrieved.contains(dbVersion)){
438            return null;
439        } else {
440            chr = ((DBSingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(EnsemblDBType.core, dbVersion)).getChromosomeByName(name);
441            this.cacheChromosome(dbVersion, chr);
442            return chr;
443        }
444    }
445    
446    @Override
447    public DAAssembledDNASequence getFragmentByName(String name, String dbVersion) throws DAOException {
448        DAAssembledDNASequence ass = null;
449        
450        if (name==null || name.isEmpty()) {
451            return null;
452        }
453
454        if (dbVersion == null || dbVersion.isEmpty()) {
455            if (this.highestDBRelease!=null && this.highestDBRelease!=0) {
456                 dbVersion = this.highestDBRelease.toString();  
457            } else {
458                return null;
459            }
460        }
461
462        if (!this.getDBVersions().contains(dbVersion)) {
463            throw new DAOException("No version " + dbVersion + " for " + this.toString());
464        }
465
466        if (this.fragments.containsKey(dbVersion) && this.fragments.get(dbVersion).containsKey(name)) {
467            return this.fragments.get(dbVersion).get(name);
468        } else  if (this.allFragmentsRetrieved.contains(dbVersion)){
469            return null;
470        } else {
471            ass = ((DBSingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(EnsemblDBType.core, dbVersion)).getFragmentByName(name);
472            this.cacheFragment(dbVersion, ass);
473            return ass;
474        }
475    }
476
477    
478     /**
479     * Method returns a List of Transcripts that have been mapped to the given Vega Identifier.
480     * (there may be  more than one Ensembl Transcript).
481     * Vega currently curates gene, transcript and protein annotations for a human 
482     * and and a few key regions of other vertebrate species. Calling this method
483     * on EnsemblGenomes (invertebrate) species will return an empty list by default
484     * via the wrapped TranscriptDAO method). 
485     * @param vegaID
486     * 
487     * @throws DAOException 
488     */
489    @Override
490    public List<DATranscript> getTranscriptsForVegaID(String vegaID) throws DAOException {
491        return this.getTranscriptsForVegaID(vegaID, null);
492    }
493    
494    /**
495     * Method returns a List of Transcripts that have been mapped to the given Vega Identifier.
496     * (there may be  more than one Ensembl Transcript).
497     * Vega currently curates gene, transcript and protein annotations for a human 
498     * and and a few key regions of other vertebrate species. Calling this method
499     * on EnsemblGenomes (invertebrate) species will return an empty list by default
500     * via the wrapped TranscriptDAO method). 
501     * @param vegaID
502     * @param dbVersion
503     * 
504     * @throws DAOException 
505     */
506    @Override
507    public List<DATranscript> getTranscriptsForVegaID(String vegaID, String dbVersion) throws DAOException {
508        List<DATranscript> transcripts = new ArrayList<DATranscript>();
509
510        if (vegaID==null || vegaID.isEmpty()) {
511            return transcripts;
512        }
513
514        if (dbVersion == null || dbVersion.isEmpty()) {
515            if (this.highestDBRelease!=null && this.highestDBRelease!=0) {
516                 dbVersion = this.highestDBRelease.toString();  
517            } else {
518                return transcripts;
519            }
520        }
521
522        try {
523            transcripts = ((DBSingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(
524                    EnsemblDBType.core, dbVersion)).getCoreFactory().getTranscriptDAO().getTranscriptsForVegaID(vegaID.trim());
525        } catch (Exception e) {
526            if (e instanceof DAOException) {
527                throw (DAOException) e;
528            } else {
529                throw new DAOException(e);
530            }
531        }
532
533        return transcripts;
534    }
535    
536    /* Method returns a List of Transcripts that have been mapped to the given CCDS Identifier 
537     * (This may be the CCDS accession or the CCDS accession.version).
538     * There may be  more than one Ensembl Transcript returned.
539     * CCDS currently curates consensus canonical transcripts for human and mouse. Calling this method
540     * on EnsemblGenomes (invertebrate) species will return an empty list by default
541     * via the wrapped TranscriptDAO method). 
542     * @param ccdsID
543     * 
544     * @throws DAOException 
545     */    
546    @Override
547    public List<DATranscript> getTranscriptsForCcdsID(String ccdsID) throws DAOException {
548        return this.getTranscriptsForCcdsID(ccdsID, null);
549    }
550    
551    /**
552     * Method returns a List of Transcripts that have been mapped to the given CCDS Identifier 
553     * (This may be the CCDS accession or the CCDS accession.version).
554     * There may be  more than one Ensembl Transcript returned.
555     * CCDS currently curates consensus canonical transcripts for human and mouse. Calling this method
556     * on EnsemblGenomes (invertebrate) species will return an empty list by default
557     * via the wrapped TranscriptDAO method). 
558     * @param ccdsID
559     * @param dbVersion
560     * 
561     * @throws DAOException 
562     */
563    @Override 
564    public List<DATranscript> getTranscriptsForCcdsID(String ccdsID, String dbVersion) throws DAOException {
565        List<DATranscript> transcripts = new ArrayList<DATranscript>();
566
567        if (ccdsID==null || ccdsID.isEmpty()) {
568            return transcripts;
569        }
570
571        if (dbVersion == null || dbVersion.isEmpty()) {
572            if (this.highestDBRelease!=null && this.highestDBRelease!=0) {
573                 dbVersion = this.highestDBRelease.toString();  
574            } else {
575                return transcripts;
576            }
577        }
578
579        try {
580            transcripts = ((DBSingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(
581                    EnsemblDBType.core, dbVersion)).getCoreFactory().getTranscriptDAO().getTranscriptsForCcdsID(ccdsID.trim());
582        } catch (Exception e) {
583            if (e instanceof DAOException) {
584                throw (DAOException) e;
585            } else {
586                throw new DAOException(e);
587            }
588        }
589
590        return transcripts;
591    }
592    
593     /**
594     * Method returns a List of Translations that have been mapped to the given Vega Identifier.
595     * (there may be  more than one Ensembl Translation).
596     * Vega currently curates gene, transcript and protein annotations for a human 
597     * and and a few key regions of other vertebrate species. Calling this method
598     * on EnsemblGenomes (invertebrate) species will return an empty list by default
599     * via the wrapped TranslationDAO method).  
600     * @param vegaID
601
602     * 
603     * @throws DAOException 
604     */
605    @Override
606    public List<DATranslation> getTranslationsForVegaID(String vegaID) throws DAOException {
607        return this.getTranslationsForVegaID(vegaID, null);
608    }
609    
610    /**
611     * Method returns a List of Translations that have been mapped to the given Vega Identifier.
612     * (there may be  more than one Ensembl Translation).
613     * Vega currently curates gene, transcript and protein annotations for a human 
614     * and and a few key regions of other vertebrate species. Calling this method
615     * on EnsemblGenomes (invertebrate) species will return an empty list by default
616     * via the wrapped TranslationDAO method).  
617     * @param vegaID
618     * @param dbVersion
619     * 
620     * @throws DAOException 
621     */
622    @Override
623    public List<DATranslation> getTranslationsForVegaID(String vegaID, String dbVersion) throws DAOException {
624        List<DATranslation> translations = new ArrayList<DATranslation>();
625
626        if (vegaID==null || vegaID.isEmpty()) {
627            return translations;
628        }
629
630        if (dbVersion == null || dbVersion.isEmpty()) {
631            if (this.highestDBRelease!=null && this.highestDBRelease!=0) {
632                 dbVersion = this.highestDBRelease.toString();  
633            } else {
634                return translations;
635            }
636        }
637
638        try {
639            translations = ((DBSingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(
640                    EnsemblDBType.core, dbVersion)).getCoreFactory().getTranslationDAO().getTranslationsForVegaID(vegaID.trim());
641        } catch (Exception e) {
642            if (e instanceof DAOException) {
643                throw (DAOException) e;
644            } else {
645                throw new DAOException(e);
646            }
647        }
648
649        return translations;
650    }
651    
652     /**
653     * Method returns a List of Genes that have been mapped to the given Vega Identifier.
654     * (there may be  more than one Ensembl Gene).
655     * Method returns a List of Genes that have been mapped to the given Vega Identifier.
656     * (there may be  more than one Ensembl Gene).
657     * Vega currently curates gene, transcript and protein annotations for a human 
658     * and and a few key regions of other vertebrate species. Calling this method
659     * on EnsemblGenomes (invertebrate) species will return an empty list by default
660     * via the wrapped GeneDAO method). 
661     * @param vegaID
662
663     * 
664     * @throws DAOException 
665     */
666    @Override
667    public List<DAGene> getGenesForVegaID(String vegaID) throws DAOException {
668        return this.getGenesForVegaID(vegaID, null);
669    }
670    
671    /**
672     * Method returns a List of Genes that have been mapped to the given Vega Identifier.
673     * (there may be  more than one Ensembl Gene).
674     * Vega currently curates gene, transcript and protein annotations for a human 
675     * and and a few key regions of other vertebrate species. Calling this method
676     * on EnsemblGenomes (invertebrate) species will return an empty list by default
677     * via the wrapped GeneDAO method). 
678     * @param vegaID
679     * @param dbVersion
680     * 
681     * @throws DAOException 
682     */
683    @Override
684    public List<DAGene> getGenesForVegaID(String vegaID, String dbVersion) throws DAOException {
685        List<DAGene> genes  = new ArrayList<DAGene>(); 
686        
687        if(vegaID==null || vegaID.isEmpty()) {
688            return genes;
689        }
690
691        if (dbVersion == null || dbVersion.isEmpty()) {
692            if (this.highestDBRelease!=null && this.highestDBRelease!=0) {
693                 dbVersion = this.highestDBRelease.toString();  
694            } else {
695                return genes;
696            }
697        }
698
699        try {
700            genes = ((DBSingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(
701                    EnsemblDBType.core, dbVersion)).getCoreFactory().getGeneDAO().getGenesForVegaID(vegaID.trim());
702        } catch (Exception e) {
703            if (e instanceof DAOException) {
704                throw (DAOException) e;
705            } else {
706                throw new DAOException(e);
707            }
708        }
709
710        return genes;
711    }
712
713    @Override
714    public DAGene getGeneByStableID(String stableID) throws DAOException {
715        return this.getGeneByStableID(stableID, null);
716    }
717
718    @Override
719    public DAGene getGeneByStableID(String stableID, String dbVersion) throws DAOException {
720
721        DAGene gene = null;
722        
723        if (stableID==null || stableID.isEmpty()) {
724            return null;
725        }
726
727        if (dbVersion == null || dbVersion.isEmpty()) {
728            if (this.highestDBRelease!=null && this.highestDBRelease!=0) {
729                 dbVersion = this.highestDBRelease.toString();  
730            } else {
731                return null;
732            }
733        }
734
735        try {
736            gene = ((DBSingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(
737                    EnsemblDBType.core, dbVersion)).getCoreFactory().getGeneDAO().getGeneByStableID(stableID.trim());
738        } catch (Exception e) {
739            if (e instanceof DAOException) {
740                throw (DAOException) e;
741            } else {
742                throw new DAOException(e);
743            }
744        }
745
746        return gene;
747    }
748    
749    @Override
750    public List<DAGene> getGenesForExactName(String name) throws DAOException {
751         return this.getGenesForExactName(name, null);
752    }
753    
754    @Override
755    public List<DAGene> getGenesForExactName(String name, String dbVersion) throws DAOException {
756        //return an empty list rather than null
757        List<DAGene> out = new ArrayList<DAGene>();        
758        if (name==null || name.isEmpty() || name.startsWith("%")) {
759            return out;
760        }
761        
762        if (dbVersion == null || dbVersion.isEmpty()) {
763            if (this.highestDBRelease!=null && this.highestDBRelease!=0) {
764                 dbVersion = this.highestDBRelease.toString();  
765            } else {
766                return out;
767            }
768        }
769        
770        try {
771            out = ((DBSingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(
772                    EnsemblDBType.core, dbVersion)).getCoreFactory().getGeneDAO().getGenesByExactName(name.trim());
773        } catch (Exception e) {
774            if (e instanceof DAOException) {
775                throw (DAOException) e;
776            } else {
777                throw new DAOException(e);
778            }
779        }
780        
781        return out;
782    }
783    
784    @Override
785    public List<DAGene> getGenesForNameBeginning(String name) throws DAOException {
786        if (name==null) {
787            return new ArrayList<DAGene>();
788        }        
789         return this.getGenesForExactName(name.trim()+"%", null);
790    }
791    
792    @Override
793    public List<DAGene> getGenesForNameBeginning(String name, String dbVersion) throws DAOException {
794        if (name==null) {
795            return new ArrayList<DAGene>();
796        }
797         return this.getGenesForExactName(name.trim()+"%", dbVersion);
798    }
799    
800    @Override
801    public DATranscript getTranscriptByStableID(String stableID) throws DAOException {
802        return this.getTranscriptByStableID(stableID, null);
803    }
804
805    @Override
806    public DATranscript getTranscriptByStableID(String stableID, String dbVersion) throws DAOException {
807
808        DATranscript transcript = null;
809        if (stableID==null || stableID.isEmpty()) {
810            return null;
811        }
812
813        if (dbVersion == null || dbVersion.isEmpty()) {
814            if (this.highestDBRelease!=null && this.highestDBRelease!=0) {
815                 dbVersion = this.highestDBRelease.toString();  
816            } else {
817                return null;
818            }
819        }
820
821        try {
822            transcript = ((DBSingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(
823                    EnsemblDBType.core, dbVersion)).getCoreFactory().getTranscriptDAO().getTranscriptByStableID(stableID.trim());
824        } catch (Exception e) {
825            if (e instanceof DAOException) {
826                throw (DAOException) e;
827            } else {
828                throw new DAOException(e);
829            }
830        }
831
832        return transcript;
833    }
834    
835    @Override
836    public DATranslation getTranslationByStableID(String stableID) throws DAOException {
837        return this.getTranslationByStableID(stableID, null);
838    }
839
840    @Override
841    public DATranslation getTranslationByStableID(String stableID, String dbVersion) throws DAOException {
842
843        DATranslation translation = null;
844        
845        if (stableID==null || stableID.isEmpty()) {
846            return null;
847        }
848
849        if (dbVersion == null || dbVersion.isEmpty()) {
850            if (this.highestDBRelease!=null && this.highestDBRelease!=0) {
851                 dbVersion = this.highestDBRelease.toString();  
852            } else {
853                return null;
854            }
855        }
856
857        try {
858            translation = ((DBSingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(
859                    EnsemblDBType.core, dbVersion)).getCoreFactory().getTranslationDAO().getTranslationByStableID(stableID.trim());
860        } catch (Exception e) {
861            if (e instanceof DAOException) {
862                throw (DAOException) e;
863            } else {
864                throw new DAOException("Error retrieving translation by StableID.", e);
865            }
866        }
867
868        return translation;
869    }
870
871    @Override
872    public TreeSet<String> getSchemaVersions() {
873        return this.schemaVersions;
874    }
875
876    @Override
877    public TreeSet<String> getDBVersions() {
878        return this.dbVersions;
879    }
880
881    public void setDatabaseStyleSpeciesName(String dbSpeciesName) {
882        this.databaseStyleSpeciesName = dbSpeciesName;
883    }
884    
885    public void setDatabaseStyleSpeciesName(Integer version, String dbSpeciesName) {
886        this.dbStyleNameByVersion.put(version, dbSpeciesName);
887    }
888    
889    public String getDatabaseStyleSpeciesName(Integer version) {
890        return this.dbStyleNameByVersion.get(version);
891    }
892
893    @Override
894    public String toString() {
895        return ((this.commonName != null && !this.commonName.isEmpty()) ? this.commonName : this.shortName)
896                + " (" + this.speciesBinomial + ")  ";
897    }
898
899    public DAChromosome getCachedChromosome(DAChromosome chr_in) {
900
901        if (chr_in == null) {
902            return null;
903        }
904
905        //test we have enough details on this chromosome to use the cache
906        if (chr_in.getChromosomeName() == null
907                || chr_in.getChromosomeName().isEmpty()
908                || chr_in.getDaoFactory() == null
909                || chr_in.getDaoFactory().getDBVersion() == null
910                || chr_in.getDaoFactory().getDBVersion().isEmpty()) {
911            return chr_in;
912        }
913
914        //if the cach has this db version
915        if (chromosomes.containsKey(chr_in.getDaoFactory().getDBVersion())) {
916
917            //if the version hash has a chr of this name return the cached one
918            if (chromosomes.get(chr_in.getDaoFactory().getDBVersion()).containsKey(chr_in.getChromosomeName())) {
919
920                DAChromosome c = chromosomes.get(chr_in.getDaoFactory().getDBVersion()).get(chr_in.getChromosomeName());
921                c.setAttributes(chr_in.getAttributes());
922                return c;
923            } //otherwise add this chr to the cache and return it
924            else {
925                chromosomes.get(chr_in.getDaoFactory().getDBVersion()).put(chr_in.getChromosomeName(), chr_in);
926                return chr_in;
927            }
928
929        } //put create a hash for this version, and add this named chromosome to it, before returning it
930        else {
931            chromosomes.put(chr_in.getDaoFactory().getDBVersion(), new TreeMap<String, DAChromosome>());
932            chromosomes.get(chr_in.getDaoFactory().getDBVersion()).put(chr_in.getChromosomeName(), chr_in);
933            return chr_in;
934        }
935    }
936    
937    public DAAssembledDNASequence getCachedFragment(DAAssembledDNASequence frag_in) {
938
939        if (frag_in == null) {
940            return null;
941        }
942
943        //test we have enough details on this chromosome to use the cache
944        if (frag_in.getName() == null
945                || frag_in.getName().isEmpty()
946                || frag_in.getDaoFactory() == null
947                || frag_in.getDaoFactory().getDBVersion() == null
948                || frag_in.getDaoFactory().getDBVersion().isEmpty()) {
949            return frag_in;
950        }
951
952        //if the cache has this db version
953        if (fragments.containsKey(frag_in.getDaoFactory().getDBVersion())) {
954
955            //if the version hash has a frag of this name return the cached one
956            if (fragments.get(frag_in.getDaoFactory().getDBVersion()).containsKey(frag_in.getName())) {
957
958                DAAssembledDNASequence c = fragments.get(frag_in.getDaoFactory().getDBVersion()).get(frag_in.getName());
959                c.setAttributes(frag_in.getAttributes());
960                return c;
961            } //otherwise add this frag to the cache and return it
962            else {
963                fragments.get(frag_in.getDaoFactory().getDBVersion()).put(frag_in.getName(), frag_in);
964                return frag_in;
965            }
966
967        } //put create a hash for this version, and add this named fragment to it, before returning it
968        else {
969            fragments.put(frag_in.getDaoFactory().getDBVersion(), new TreeMap<String, DAAssembledDNASequence>());
970            fragments.get(frag_in.getDaoFactory().getDBVersion()).put(frag_in.getName(), frag_in);
971            return frag_in;
972        }
973    }
974
975    @Override
976    public EnsemblComparaDivision getComparaDivision() {
977        //the default value is MULTI - used for ensembl.org
978        return comparaDivision;
979    }
980
981    public void setComparaDivision(String speciesDivision) {
982        //sets group for ensemblgenomes.org
983        this.comparaDivision = EnsemblComparaDivision.getEnsemblComparaDivisionByMetaValue(speciesDivision);
984    }
985    
986    public void setComparaDivision(EnsemblComparaDivision speciesDivision) {
987        this.comparaDivision = speciesDivision;
988    }
989
990    @Override
991    public String getAssemblyName(String dbVersion) {
992
993        String out = "";
994        if (dbVersion == null || dbVersion.isEmpty()) {
995            if (this.highestDBRelease!=null && this.highestDBRelease!=0) {
996                 dbVersion = this.highestDBRelease.toString();  
997            } else {
998                return out;
999            }
1000        }
1001
1002        if (this.assemblyNamesByVersion.get(dbVersion) == null) {
1003            if (this.getDatabaseByTypeAndVersion(EnsemblDBType.core, dbVersion) != null) {
1004                //the lazyload will be called here if required
1005                out = ((SingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(EnsemblDBType.core, dbVersion)).getAssemblyName();
1006            }
1007            this.assemblyNamesByVersion.put(dbVersion, out);
1008        }
1009
1010        out = this.assemblyNamesByVersion.get(dbVersion);
1011        return out == null ? "" : out;
1012    }
1013
1014    //non lazyload direct setter
1015    public void setAssemblyAccession(String version, String value) {
1016        this.assemblyAccessionsByVersion.put(version, value);
1017    }
1018    //non lazyload direct setter
1019
1020    public void setAssemblyName(String version, String value) {
1021        this.assemblyNamesByVersion.put(version, value);
1022    }
1023
1024    @Override
1025    public String getAssemblyAccession(String dbVersion) {
1026        String out = "";
1027        if (dbVersion == null || dbVersion.isEmpty()) {
1028            if (this.highestDBRelease!=null && this.highestDBRelease!=0) {
1029                 dbVersion = this.highestDBRelease.toString();  
1030            } else {
1031                return out;
1032            }
1033        }
1034
1035        if (this.assemblyAccessionsByVersion.get(dbVersion) == null) {
1036            if (this.getDatabaseByTypeAndVersion(EnsemblDBType.core, dbVersion) != null) {
1037                //the lazyload will be called here if required
1038                out = ((SingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(EnsemblDBType.core, dbVersion)).getAssemblyAccession();
1039            }
1040            this.assemblyAccessionsByVersion.put(dbVersion, out);
1041        }
1042
1043        out = this.assemblyAccessionsByVersion.get(dbVersion);
1044        return out == null ? "" : out;
1045    }
1046
1047    @Override
1048    public Integer getHighestDBRelease() {
1049        return this.highestDBRelease;
1050    }
1051    
1052    @Override
1053    public void setAssemblyExceptions(String version) throws DAOException {
1054        
1055        //HashMap<DAChromosome, MappingSet> results = new HashMap<DAChromosome, MappingSet>();
1056        TreeMap<String, DAChromosome> chrs = this.getChromosomes(version);
1057        
1058        if (chrs != null && !chrs.isEmpty()) {
1059
1060            try {
1061                ((DBSingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(
1062                        EnsemblDBType.core, version)).getCoreFactory().getChromosomeDAO().setAssemblyExceptions(chrs);
1063            } catch (Exception e) {
1064                if (e instanceof DAOException) {
1065                    throw (DAOException) e;
1066                } else {
1067                    throw new DAOException(e);
1068                }
1069            }
1070
1071        }
1072        
1073        //this.assemblyExceptions.put(version, results);
1074    }
1075
1076    @Override
1077    public String getAssemblyAccessionStem() {
1078        return this.getAssemblyAccession(null).split("\\.")[0];
1079    }
1080    
1081    @Override
1082    public String getAssemblyAccessionStem(String dbVersion) {
1083        return this.getAssemblyAccession(dbVersion).split("\\.")[0];
1084    }
1085
1086    public String getUrlName() {
1087        return urlName;
1088    }
1089
1090    public void setUrlName(String urlName) {
1091        this.urlName = urlName;
1092    }
1093
1094    @Override
1095    public boolean isInPanCompara(String dbVersion) {
1096        if (registry==null
1097                || !this.getDBVersions().contains(dbVersion)) {
1098            
1099            return false;
1100        } 
1101        return this.registry.isSpeciesInPanHomology(this, dbVersion);
1102    }
1103}