001    /**
002     * Copyright (C) 2010 The Roslin Institute <contact andy.law@roslin.ed.ac.uk>
003     *
004     * This file is part of the Ensembl Java API demonstration project developed by the
005     * Bioinformatics Group at The Roslin Institute, The Royal (Dick) School of
006     * Veterinary Studies, University of Edinburgh.
007     *
008     * This is free software: you can redistribute it and/or modify
009     * it under the terms of the GNU General Public License (version 3) as published by
010     * the Free Software Foundation.
011     *
012     * This software is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
015     * GNU General Public License for more details.
016     *
017     * You should have received a copy of the GNU General Public License
018     * in this software distribution. If not, see <http://www.gnu.org/licenses/gpl-3.0.html/>.
019     */
020    package uk.ac.roslin.ensembl.dao.database;
021    
022    import java.util.HashMap;
023    import java.util.List;
024    import java.util.TreeMap;
025    import java.util.TreeSet;
026    import uk.ac.roslin.ensembl.datasourceaware.core.DAChromosome;
027    import uk.ac.roslin.ensembl.datasourceaware.core.DAGene;
028    import uk.ac.roslin.ensembl.exception.DAOException;
029    import uk.ac.roslin.ensembl.model.core.Species;
030    import uk.ac.roslin.ensembl.model.database.CoreDatabase;
031    import uk.ac.roslin.ensembl.model.database.Database;
032    import uk.ac.roslin.ensembl.model.database.DatabaseType;
033    import uk.ac.roslin.ensembl.config.EnsemblDBType;
034    import uk.ac.roslin.ensembl.config.EnsemblComparaDivision;
035    import uk.ac.roslin.ensembl.model.database.Registry;
036    import uk.ac.roslin.ensembl.model.database.SingleSpeciesCoreDatabase;
037    
038    public class DBSpecies implements Species {
039    
040        protected String databaseStyleSpeciesName = "";
041        protected String speciesBinomial = "";
042        protected String commonName = "";
043        protected String comparaName = "";
044        protected String shortName = "";
045        protected String mostRecentEnsemblSchemaVersion = "";
046        protected String mostRecentDBRelease = "";
047        protected String taxonomyID = "";
048        protected String ensemblStablePrefix = "";
049        protected TreeSet<String> aliases = new TreeSet<String>();
050        protected Registry registry = null;
051        private TreeSet<DBSingleSpeciesDatabase> databases = new TreeSet<DBSingleSpeciesDatabase>();
052        private DBSingleSpeciesCoreDatabase currentCoreDatabase;
053        private final Integer dBSpeciesID = 1;
054        //this acts as the chromosome cache, hashed by version then by name
055        TreeMap<String, TreeMap<String, DAChromosome>> chromosomes =
056                new TreeMap<String, TreeMap<String, DAChromosome>>();
057        private TreeSet<String> allChromosomesRetrieved = new TreeSet<String>();
058        private TreeSet<String> versions = null;
059        EnsemblDBType dbType;
060        //default value
061        EnsemblComparaDivision comparaDivision = EnsemblComparaDivision.MULTI;
062    
063        public DBSpecies() {
064            dbType = EnsemblDBType.core;
065        }
066    
067        public DBSpecies(DBSingleSpeciesCoreDatabase database) {
068            this();
069            this.registry = database.getRegistry();
070            mostRecentEnsemblSchemaVersion = registry.getMostRecentEnsemblVersion();
071            mostRecentDBRelease = registry.getMostRecentDBVersion();
072    
073            if (database.getDBVersion().equals(registry.getMostRecentDBVersion())) {
074                this.currentCoreDatabase = database;
075            }
076    
077            this.databases.add(database);
078    
079    //        //from dbVersion 59 releases, the meta table holds the species.production_name,
080    //        //species.short_name and species.scientific_name meta_keys
081    //        //making this obsolete - but we will need to perform it in DBDatabaseDAO if
082    //        //it is a pre59 release
083    //        databaseStyleSpeciesName=this.currentCoreDatabase.getDbSpeciesName();
084    //        speciesBinomial = databaseStyleSpeciesName.replaceFirst( databaseStyleSpeciesName.substring(0, 1), (databaseStyleSpeciesName.substring(0,1)).toUpperCase() ).replace("_"," ");
085    //        aliases.add(speciesBinomial);
086    
087        }
088    
089        public TreeSet<String> getVersions() {
090            if (versions != null) {
091                return versions;
092            } else {
093                versions = new TreeSet<String>();
094                for (DBDatabase db : this.getDatabasesByType(EnsemblDBType.core)) {
095                    versions.add(db.getDBVersion());
096                }
097                return versions;
098            }
099        }
100    
101        @Override
102        public TreeSet<String> getAliases() {
103            return aliases;
104        }
105    
106        //will be overridden in DBCollectionSpecies
107        @Override
108        public void setProperty(HashMap row) {
109    
110            String key = (String) row.get("key");
111            String value = (String) row.get("value");
112    
113            if (key.equals("species.stable_id_prefix")) {
114                this.ensemblStablePrefix = value;
115            } else if (key.equals("species.common_name")
116                    ||key.equals("species.ensembl_common_name")) {
117                aliases.add(value);
118                this.commonName = value;
119            } else if (key.equals("species.short_name")) {
120                aliases.add(value);
121                this.shortName = value;
122            } else if (key.equals("species.scientific_name")) {
123                aliases.add(value);
124                this.speciesBinomial = value;
125            } else if (key.equals("species.production_name")) {
126                aliases.add(value);
127                this.databaseStyleSpeciesName = value;
128            } else if (key.equals("species.taxonomy_id")) {
129                aliases.add(value);
130                this.taxonomyID = value;
131            } else if (key.equals("species.alias")
132               //     || key.equals("species.ensembl_common_name")
133                    || key.equals("species.ensembl_alias_name")) {
134                aliases.add(value);
135            }
136        }
137    
138        @Override
139        public CoreDatabase getCurrentCoreDatabase() {
140            return currentCoreDatabase;
141        }
142    
143        @Override
144        public String getCommonName() {
145            return commonName;
146        }
147    
148        @Override
149        public String getShortName() {
150            return shortName;
151        }
152    
153        public void setShortName(String name) {
154            shortName = name;
155        }
156    
157        @Override
158        public String getDatabaseStyleName() {
159            return databaseStyleSpeciesName;
160        }
161    
162        @Override
163        public TreeSet<? extends DBDatabase> getDatabases() {
164            return databases;
165        }
166    
167        @Override
168        public void addDatabases(TreeSet<? extends Database> databases) {
169    
170            for (Database d : databases) {
171                try {
172                    this.databases.add((DBSingleSpeciesDatabase) d);
173                } catch (Exception e) {
174                }
175            }
176        }
177    
178        @Override
179        public void addDatabase(Database database) {
180    
181            try {
182                this.databases.add((DBSingleSpeciesDatabase) database);
183            } catch (Exception e) {
184            }
185    
186        }
187    
188        @Override
189        public String getEnsemblStablePrefix() {
190            return ensemblStablePrefix;
191        }
192    
193        @Override
194        public String getSpeciesBinomial() {
195            return speciesBinomial;
196        }
197    
198        @Override
199        public String getTaxonomyID() {
200            return taxonomyID;
201        }
202    
203        @Override
204        public TreeSet<? extends DBDatabase> getDatabasesByType(DatabaseType type) {
205            TreeSet<DBSingleSpeciesDatabase> out = new TreeSet<DBSingleSpeciesDatabase>();
206            for (DBDatabase d : databases) {
207                if (d.getType() == type) {
208                    out.add((DBSingleSpeciesDatabase) d);
209                }
210            }
211            return out;
212        }
213    
214        @Override
215        public TreeSet<? extends DBDatabase> getDatabasesByVersion(String version) {
216            TreeSet<DBSingleSpeciesDatabase> out = new TreeSet<DBSingleSpeciesDatabase>();
217            for (DBDatabase d : databases) {
218                if (d.getDBVersion().equals(version)) {
219                    out.add((DBSingleSpeciesDatabase) d);
220                }
221            }
222            return out;
223        }
224    
225        @Override
226        public DBDatabase getDatabaseByTypeAndVersion(DatabaseType type, String version) {
227    
228            for (DBDatabase d : databases) {
229                if (d.getDBVersion().equalsIgnoreCase(version) && d.getType() == type) {
230                    return d;
231                }
232            }
233            return null;
234        }
235    
236        public void setCommonName(String commonName) {
237            this.commonName = commonName;
238        }
239    
240        public void setEnsemblStablePrefix(String ensemblStablePrefix) {
241            this.ensemblStablePrefix = ensemblStablePrefix;
242        }
243    
244        public void setSpeciesBinomial(String speciesBinomial) {
245            this.speciesBinomial = speciesBinomial;
246        }
247    
248        public void setTaxonomyID(String taxonomyID) {
249            this.taxonomyID = taxonomyID;
250        }
251    
252        @Override
253        public Integer getDBSpeciesID(String version) {
254            return this.dBSpeciesID;
255        }
256    
257        public Integer getDBSpeciesID() {
258            return this.dBSpeciesID;
259        }
260    
261        @Override
262        public String getComparaName() {
263            //for a single species Database the compara database name is the binomial
264            //but for a collection species the productionname/comparaname/dbname
265            return this.comparaName;
266        }
267    
268        public void setComparaName(String comparaName) {
269            //for a single species Database the compara database name is the binomial
270            //but for a collection species the productionname/comparaname/dbname
271            this.comparaName = comparaName;
272        }
273    
274        @Override
275        public TreeMap<String, DAChromosome> getChromosomes() throws DAOException {
276            return getChromosomes(null);
277        }
278    
279        @Override
280        public TreeMap<String, DAChromosome> getChromosomes(String dbVersion) throws DAOException {
281    
282            if (dbVersion == null || dbVersion.isEmpty()) {
283                dbVersion = mostRecentDBRelease;
284            }
285    
286            if (!this.getVersions().contains(dbVersion)) {
287                throw new DAOException("No version " + dbVersion + " for " + this.toString());
288            }
289    
290            if (this.allChromosomesRetrieved.contains(dbVersion)) {
291                return this.chromosomes.get(dbVersion);
292            }
293    
294            List<DAChromosome> chrs = null;
295    
296            if (!this.chromosomes.containsKey(dbVersion)) {
297                this.chromosomes.put(dbVersion, new TreeMap<String, DAChromosome>());
298            }
299    
300            chrs = ((DBSingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(EnsemblDBType.core, dbVersion)).getChromosomes();
301    
302            this.allChromosomesRetrieved.add(dbVersion);
303    
304            for (DAChromosome c : chrs) {
305                if (!chromosomes.get(dbVersion).containsKey(c.getChromosomeName())) {
306                    chromosomes.get(dbVersion).put(c.getChromosomeName(), c);
307                }
308            }
309    
310            return this.chromosomes.get(dbVersion);
311        }
312    
313        @Override
314        public DAChromosome getChromosomeByName(String name) throws DAOException {
315            return this.getChromosomeByName(name, null);
316        }
317    
318        @Override
319        public DAChromosome getChromosomeByName(String name, String dbVersion) throws DAOException {
320            DAChromosome chr = null;
321    
322            if (dbVersion == null || dbVersion.isEmpty()) {
323                dbVersion = mostRecentDBRelease;
324            }
325    
326            if (!this.getVersions().contains(dbVersion)) {
327                throw new DAOException("No version " + dbVersion + " for " + this.toString());
328            }
329    
330            if (!this.chromosomes.containsKey(dbVersion)) {
331    
332                this.chromosomes.put(dbVersion, new TreeMap<String, DAChromosome>());
333            }
334    
335            if (this.chromosomes.get(dbVersion).containsKey(name)) {
336                return this.chromosomes.get(dbVersion).get(name);
337            } else {
338    
339                chr = ((DBSingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(EnsemblDBType.core, dbVersion)).getChromosomeByName(name);
340            }
341    
342            if (chr != null) {
343                chromosomes.get(dbVersion).put(name, chr);
344            }
345    
346            return chr;
347        }
348    
349        @Override
350        public DAGene getGeneByID(Integer id) throws DAOException {
351            return this.getGeneByID(id, null);
352        }
353    
354        @Override
355        public DAGene getGeneByID(Integer id, String dbVersion) throws DAOException {
356    
357            DAGene gene = null;
358    
359            if (dbVersion == null || dbVersion.isEmpty()) {
360                dbVersion = this.mostRecentDBRelease;
361            }
362    
363            try {
364            gene = ((DBSingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(
365                    EnsemblDBType.core, dbVersion)).getCoreFactory().getGeneDAO().getGeneByID(id);
366            } catch (Exception e) {
367                if (e instanceof DAOException) {
368                    throw (DAOException) e;
369                } else {
370                    throw new DAOException(e);
371                }
372            }
373    
374            return gene;
375        }
376    
377        @Override
378        public DAGene getGeneByStableID(String stableID) throws DAOException {
379            return this.getGeneByStableID(stableID, null);
380        }
381    
382        @Override
383        public DAGene getGeneByStableID(String stableID, String dbVersion) throws DAOException {
384    
385            DAGene gene = null;
386    
387            if (dbVersion == null || dbVersion.isEmpty()) {
388                dbVersion = this.mostRecentDBRelease;
389            }
390    
391           try {
392            gene = ((DBSingleSpeciesCoreDatabase) this.getDatabaseByTypeAndVersion(
393                    EnsemblDBType.core, dbVersion)).getCoreFactory().getGeneDAO().getGeneByStableID(stableID.trim());
394                } catch (Exception e) {
395                if (e instanceof DAOException) {
396                    throw (DAOException) e;
397                } else {
398                    throw new DAOException(e);
399                }
400            }
401    
402            return gene;
403        }
404    
405        @Override
406        public TreeSet<String> getSchemaVersions() {
407            TreeSet<String> out = new TreeSet<String>();
408    
409            for (Database d : this.getDatabasesByType(dbType)) {
410                out.add(d.getSchemaVersion());
411            }
412    
413            return out;
414        }
415    
416        @Override
417        public TreeSet<String> getDBVersions() {
418            TreeSet<String> out = new TreeSet<String>();
419    
420            for (Database d : this.getDatabasesByType(dbType)) {
421                out.add(d.getDBVersion());
422            }
423    
424            return out;
425        }
426    
427        public void setDatabaseStyleSpeciesName(String dbSpeciesName) {
428            this.databaseStyleSpeciesName = dbSpeciesName;
429        }
430    
431        @Override
432        public String toString() {
433            return ((this.commonName!= null && !this.commonName.isEmpty() ) ? this.commonName : this.shortName )
434                    + " (" + this.speciesBinomial + ")  ";
435        }
436    
437        public DAChromosome getCachedChromosome(DAChromosome chr_in) {
438    
439            if (chr_in == null) {
440                return null;
441            }
442    
443            //test we have enough details on this chromosome to use the cache
444            if (chr_in.getChromosomeName()== null
445                    || chr_in.getChromosomeName().isEmpty()
446                    || chr_in.getDaoFactory() == null
447                    || chr_in.getDaoFactory().getDBVersion()==null
448                    || chr_in.getDaoFactory().getDBVersion().isEmpty() ) {
449                return chr_in;
450            }
451    
452            //if the cach has this db version
453            if (chromosomes.containsKey(chr_in.getDaoFactory().getDBVersion())) {
454    
455                //if the version hash has a chr of this name return the cached one
456                if (chromosomes.get(chr_in.getDaoFactory().getDBVersion())
457                        .containsKey(chr_in.getChromosomeName())) {
458                    return chromosomes.get(chr_in.getDaoFactory().getDBVersion())
459                            .get(chr_in.getChromosomeName());
460                }
461                //otherwise add this chr to the cache and return it
462                else {
463                    chromosomes.get(chr_in.getDaoFactory().getDBVersion())
464                            .put(chr_in.getChromosomeName(), chr_in);
465                    return chr_in;
466                }
467    
468            }
469            //put create a hash for this version, and add this named chromosome to it, before returning it
470            else {
471                chromosomes.put(chr_in.getDaoFactory().getDBVersion(), new TreeMap<String, DAChromosome>());
472                chromosomes.get(chr_in.getDaoFactory().getDBVersion())
473                        .put(chr_in.getChromosomeName(), chr_in);
474                return chr_in;
475            }
476        }
477    
478        public EnsemblComparaDivision getComparaDivision() {
479            return comparaDivision;
480        }
481    
482        public void setComparaDivision(String speciesDivision) {
483            this.comparaDivision = EnsemblComparaDivision.getEnsemblComparaDivisionByMetaValue(speciesDivision);
484        }
485    
486        @Override
487        public String getAssembly() {
488            return this.getAssembly(null);
489        }
490    
491        @Override
492        public String getAssembly(String dbVersion) {
493    
494            if (dbVersion == null || dbVersion.isEmpty()) {
495                dbVersion = mostRecentDBRelease;
496            }
497            
498          if (this.getDatabaseByTypeAndVersion(EnsemblDBType.core, dbVersion)!=null) {
499              return ((SingleSpeciesCoreDatabase)
500                      this.getDatabaseByTypeAndVersion(EnsemblDBType.core, dbVersion)).getAssembly();
501          } else {
502                return null;
503          }
504        }
505    
506    
507    }