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    
021    package uk.ac.roslin.ensembl.dao.database;
022    
023    import java.util.ArrayList;
024    import java.util.HashMap;
025    import java.util.Iterator;
026    import java.util.List;
027    import java.util.Set;
028    import java.util.TreeMap;
029    import uk.ac.roslin.ensembl.datasourceaware.core.DAChromosome;
030    import uk.ac.roslin.ensembl.datasourceaware.core.DACoordinateSystem;
031    import uk.ac.roslin.ensembl.dao.database.factory.DBDAOCollectionCoreFactory;
032    import uk.ac.roslin.ensembl.dao.database.factory.DBDAOCollectionFactory;
033    import uk.ac.roslin.ensembl.exception.ConfigurationException;
034    import uk.ac.roslin.ensembl.exception.DAOException;
035    import uk.ac.roslin.ensembl.model.ObjectType;
036    import uk.ac.roslin.ensembl.model.core.CoordinateSystem;
037    import uk.ac.roslin.ensembl.model.core.Species;
038    import uk.ac.roslin.ensembl.model.database.CollectionCoreDatabase;
039    import uk.ac.roslin.ensembl.model.core.CollectionSpecies;
040    import uk.ac.roslin.ensembl.config.EnsemblCoordSystemType;
041    import uk.ac.roslin.ensembl.config.EnsemblDBType;
042    import uk.ac.roslin.ensembl.config.FeatureType;
043    import uk.ac.roslin.ensembl.model.database.Registry;
044    
045    /**
046     *
047     * @author paterson
048     */
049    public class DBCollectionCoreDatabase extends DBCollectionDatabase  implements CollectionCoreDatabase {
050    
051    
052        private TreeMap<DBCollectionSpecies, TreeMap<Integer, DACoordinateSystem>> CSHash = new TreeMap<DBCollectionSpecies, TreeMap<Integer, DACoordinateSystem>>();
053    
054        private TreeMap<DBCollectionSpecies, DACoordinateSystem> seqLevelCSHash = new TreeMap<DBCollectionSpecies, DACoordinateSystem>();
055        private TreeMap<DBCollectionSpecies, DACoordinateSystem> chrLevelCSHash = new TreeMap<DBCollectionSpecies, DACoordinateSystem>();
056        private TreeMap<DBCollectionSpecies, DACoordinateSystem> topLevelCSHash = new TreeMap<DBCollectionSpecies, DACoordinateSystem>();
057    
058        private TreeMap<DBCollectionSpecies, DBDAOCollectionCoreFactory> factoryHash = new TreeMap<DBCollectionSpecies, DBDAOCollectionCoreFactory>();
059    
060        private TreeMap<DBCollectionSpecies, HashMap<FeatureType, HashMap<DACoordinateSystem, Integer>>>  featureCSHash
061                = new TreeMap<DBCollectionSpecies, HashMap<FeatureType, HashMap<DACoordinateSystem, Integer>>>();
062    
063        private TreeMap<DBCollectionSpecies, HashMap<DACoordinateSystem, List<FeatureType>>>    CSFeatureHash
064                = new TreeMap<DBCollectionSpecies, HashMap<DACoordinateSystem, List<FeatureType>>>();
065    
066    
067    //    private TreeMap<DBCollectionSpecies, String> speciesGeneBuildLevelHash = new TreeMap<DBCollectionSpecies, String>();
068    //    private TreeMap<DBCollectionSpecies, String> speciesExonBuildLevelHash = new TreeMap<DBCollectionSpecies, String>();
069    //    private TreeMap<DBCollectionSpecies, String> speciesTranscriptBuildLevelHash = new TreeMap<DBCollectionSpecies, String>();
070    
071        private TreeMap<DBCollectionSpecies, HashMap<FeatureType, String>> speciesBuildLevels = new TreeMap<DBCollectionSpecies, HashMap<FeatureType,String>>();
072    
073        public DBCollectionCoreDatabase(String db_name, EnsemblDBType type, Registry registry) throws ConfigurationException {
074            super(db_name, type, registry);
075        }
076    
077    
078        @Override
079        public DBDAOCollectionCoreFactory getCoreFactory(Species sp) {
080    
081    
082    
083            if (sp == null || collection ==null || !this.collection.getSpecies().contains(sp)) {
084                return null;
085            }
086    
087            DBCollectionSpecies species = (DBCollectionSpecies) sp;
088    
089            if (this.factoryHash.containsKey(species)) {
090                return this.factoryHash.get(species);
091            } else {
092                DBDAOCollectionCoreFactory f = null;
093    
094                try {
095                    f = (DBDAOCollectionCoreFactory) DBDAOCollectionFactory.makeFactory(this,  species);
096                    this.factoryHash.put(species, f);
097                } catch (Exception ex) {
098                }
099                return f;
100    
101            }
102        }
103    
104        @Override
105        public DACoordinateSystem getChromosomeLevelCS(Species species) throws DAOException {
106    
107            if (species == null ||  this.collection == null || !this.getCollection().getSpecies().contains(species)) {
108                return null;
109            }
110    
111            DBCollectionSpecies sp = (DBCollectionSpecies) species;
112    
113            if (!this.chrLevelCSHash.containsKey(sp)) {
114                this.lazyLoadCoordinateSytems(sp);
115            }
116    
117            return this.chrLevelCSHash.get(sp);
118    
119        }
120    
121        @Override
122        public DACoordinateSystem getSequenceLevelCS(Species species) throws DAOException {
123            
124            if (species == null || this.collection == null || !this.getCollection().getSpecies().contains(species)) {
125                return null;
126            }
127            DBCollectionSpecies sp = (DBCollectionSpecies) species;
128            if (!this.seqLevelCSHash.containsKey(sp)) {
129                this.lazyLoadCoordinateSytems(sp);
130            }
131    
132            return this.seqLevelCSHash.get(sp);
133        }
134    
135        @Override
136        public DACoordinateSystem getTopLevelCS(Species species) throws DAOException {
137            
138            if ( species == null || this.collection == null || !this.getCollection().getSpecies().contains(species)) {
139                return null;
140            }
141            DBCollectionSpecies sp = (DBCollectionSpecies) species;
142            if (!this.topLevelCSHash.containsKey(sp)) {
143                this.lazyLoadCoordinateSytems(sp);
144            }
145    
146            return this.topLevelCSHash.get(sp);
147        }
148    
149    
150        private List<DACoordinateSystem> fetchCS(DBCollectionSpecies species) throws DAOException {
151    
152            List<DACoordinateSystem> coords = new ArrayList<DACoordinateSystem>();
153            if (species == null || collection ==null || !this.collection.getSpecies().contains(species)) {
154                return coords;
155            }
156    
157            //can throw DAOException
158            if ( this.getCoreFactory(species)!=null) {
159                coords = this.getCoreFactory(species).getCoordinateSystemDAO().
160                    getCoordinateSystems();
161            } else {
162               return coords;
163            }
164            return coords;
165        }
166    
167    
168        private void lazyLoadCoordinateSytems(DBCollectionSpecies species)  throws DAOException {
169    
170            if (species == null || collection ==null || !this.collection.getSpecies().contains(species)) {
171                return ;
172            }
173    
174            List<DACoordinateSystem> coords = this.fetchCS(species);
175    
176            if (!coords.isEmpty()) {
177                   this.setCoordinateSytems(species, coords);
178            }
179    
180                //set null values to prevent repeating lazy load
181    
182                if (!this.chrLevelCSHash.containsKey(species)) {
183                    this.chrLevelCSHash.put(species, null);
184                }
185                if (!this.topLevelCSHash.containsKey(species)) {
186                    this.topLevelCSHash.put(species, null);
187                }
188                if (!this.seqLevelCSHash.containsKey(species)) {
189                    this.seqLevelCSHash.put(species, null);
190                }
191    
192        }
193    
194        private void setCoordinateSytems(DBCollectionSpecies species, List<DACoordinateSystem> coords ) throws DAOException {
195    
196            if (species == null || collection ==null || !this.collection.getSpecies().contains(species)) {
197                return ;
198            }
199    
200            TreeMap<Integer, DACoordinateSystem> hash1 = new TreeMap<Integer, DACoordinateSystem>();
201    
202    
203            //set  the is for the top, chromosome and sequence levels
204    
205            for (DACoordinateSystem cs: coords) {
206    
207                hash1.put(cs.getId(), cs);
208    
209                if (cs.getRank()==1) {
210    
211                    this.topLevelCSHash.put(species, cs);
212    
213                    if (cs.getType()==EnsemblCoordSystemType.chromosome) {
214                        this.chrLevelCSHash.put(species, cs);
215                    }
216                }
217    
218                if (cs.isSequenceLevel()) {
219                        this.seqLevelCSHash.put(species, cs);
220                    }
221            }
222    
223            this.CSHash.put(species, hash1);
224    
225            //if the top rank wasnt chromosome level, find the highest ranked chromosome level
226    
227            if (!this.chrLevelCSHash.containsKey(species)) {
228    
229                TreeMap <Integer, DACoordinateSystem> temp = new TreeMap <Integer, DACoordinateSystem>();
230    
231                for (DACoordinateSystem cs: coords) {
232                    temp.put(cs.getRank(), cs);
233                }
234    
235                Iterator<Integer> it = temp.keySet().iterator();
236                while (it.hasNext()) {
237                    DACoordinateSystem cs = temp.get(it.next());
238                    if (cs.getType()==EnsemblCoordSystemType.chromosome) {
239                        this.chrLevelCSHash.put(species, cs);
240                        break;
241                    }
242                }
243            }
244            }
245    
246        @Override
247        public void setBuildLevels(Species species, HashMap<String, String> keyedValues) {
248    
249            if (species == null || collection ==null || !this.collection.getSpecies().contains(species)) {
250                return ;
251            }
252    
253            HashMap<FeatureType, String> map = new HashMap<FeatureType, String>();
254    
255            for (String key : keyedValues.keySet() ) {
256    
257                String temp = key.replace("build.level", "");
258    
259                if (FeatureType.getFeatureType(temp)!= null ) {
260                    map.put(FeatureType.getFeatureType(temp), keyedValues.get(key));
261                }
262    
263            }
264    
265            this.speciesBuildLevels.put((DBCollectionSpecies) species, map);
266        }
267    
268        @Override
269        @SuppressWarnings("element-type-mismatch")
270        public String getBuildLevel(Species species, String featureKey) throws DAOException{
271    
272            if (species == null || collection ==null || !this.collection.getSpecies().contains(species)) {
273                return null;
274            }
275    
276            String out = null;
277    
278            if (this.speciesBuildLevels.get(species)!= null) {
279                out = this.speciesBuildLevels.get(species).get(FeatureType.getFeatureType(featureKey));
280            }
281            return out;
282        }
283    
284        //dont really want this public - just for testing
285        public HashMap<FeatureType, String> getBuildLevels(CollectionSpecies species) {
286            if (species == null || collection ==null || !this.collection.getSpecies().contains(species)) {
287                return null;
288            }
289            return this.speciesBuildLevels.get(species);
290        }
291    
292        private void setFeatureCSHash(DBCollectionSpecies sp) throws DAOException {
293    
294            if (sp == null || collection ==null || !this.collection.getSpecies().contains(sp)) {
295                return;
296            }
297    
298            if (!this.CSHash.containsKey(sp)) {
299                this.lazyLoadCoordinateSytems(sp);
300            }
301    
302    
303            HashMap<DACoordinateSystem, List<FeatureType>> hash1 = new HashMap<DACoordinateSystem, List<FeatureType>>();
304    
305            for (DACoordinateSystem c : this.CSHash.get(sp).values()) {
306                hash1.put(c, new ArrayList<FeatureType>());
307    
308            }
309    
310            this.CSFeatureHash.put(sp, hash1);
311    
312            this.featureCSHash.put(sp,  new  HashMap<FeatureType, HashMap<DACoordinateSystem, Integer>>() );
313    
314            try {
315    
316                this.getCoreFactory(sp).getCoordinateSystemDAO().setFeatureCS();
317    
318            } catch (DAOException e) {
319                throw e;
320            }
321    
322        }
323    
324        @Override
325        public void addFeatureCS(String featureType, Integer csID, Integer maxLength, Species sp) {
326    
327            if (sp == null || collection ==null || !this.collection.getSpecies().contains(sp)) {
328                return ;
329            }
330    
331            FeatureType localType = null;
332            DACoordinateSystem cs = null;
333    
334            localType = FeatureType.getFeatureType(featureType);
335            cs = this.CSHash.get(sp).get(csID);
336    
337            if (localType == null || cs == null) {
338                return;
339            } else {
340                if (!this.featureCSHash.get(sp).containsKey(localType)) {
341                    this.featureCSHash.get(sp).put(localType, new HashMap<DACoordinateSystem, Integer>());
342                }
343                this.featureCSHash.get(sp).get(localType).put(cs, maxLength);
344    
345                this.CSFeatureHash.get(sp).get(cs).add(localType);
346    
347            }
348    
349    
350        }
351    
352    
353        @Override
354        public Set<DACoordinateSystem> getCSForFeature(Species sp, ObjectType feature) throws DAOException {
355    
356            if (sp == null || collection ==null || !this.collection.getSpecies().contains(sp)) {
357                return null;
358            }
359    
360                if (!this.featureCSHash.containsKey(sp)) {
361                    this.setFeatureCSHash((DBCollectionSpecies) sp);
362                }
363    
364    
365            if (this.featureCSHash.containsKey(sp)
366                    && this.featureCSHash.get(sp).containsKey(feature)) {
367                return this.featureCSHash.get(sp).get(feature).keySet();
368            } else {
369    
370                return null;
371            }
372        }
373    
374        @Override
375        public List<FeatureType> getFeaturesForCS(Species sp, CoordinateSystem coordSys) throws DAOException {
376    
377            if (sp== null || collection ==null || !this.collection.getSpecies().contains(sp)) {
378                return null;
379            }
380    
381                if (!this.featureCSHash.containsKey(sp)) {
382                    this.setFeatureCSHash((DBCollectionSpecies) sp);
383                }
384    
385            if (this.CSFeatureHash.containsKey(sp)
386                    && this.CSFeatureHash.get(sp).containsKey(coordSys)) {
387                return this.CSFeatureHash.get(sp).get(coordSys);
388            } else {
389                return null;
390            }
391        }
392    
393        @Override
394        public Integer getMaxLengthForFeature(Species sp, ObjectType feature, CoordinateSystem cs) throws DAOException {
395    
396            if (sp == null || collection ==null || !this.collection.getSpecies().contains(sp)) {
397                return null;
398            }
399    
400            if ( feature == null || cs == null ) {
401                return null;
402            }
403    
404                if (!this.featureCSHash.containsKey(sp) ) {
405                    this.setFeatureCSHash((DBCollectionSpecies) sp);
406                }
407    
408            if (this.featureCSHash.containsKey(sp)
409                    && this.featureCSHash.get(sp).containsKey(feature)
410                    && this.featureCSHash.get(sp).get(feature).containsKey(cs)) {
411                return this.featureCSHash.get(sp).get(feature).get(cs); 
412            } else {
413                return null;
414            }
415    
416        }
417    
418        @Override
419        public DACoordinateSystem getBuildCoordSystem(Species species, String featureType) throws DAOException{
420    
421            if (species == null || collection ==null || !this.collection.getSpecies().contains(species)
422                    || this.speciesBuildLevels.get(species) == null ||
423                    featureType ==null || featureType.isEmpty()) {
424                return null;
425            }
426    
427                if (FeatureType.getFeatureType(featureType) != null) {
428                    String level = this.speciesBuildLevels.get(species).get(FeatureType.getFeatureType(featureType));
429                    if (level.equalsIgnoreCase("toplevel")) {
430                        return this.topLevelCSHash.get(species);
431                    } else {
432                        return null;
433                    }
434    
435    //                //are there other values possible?
436    //                else if (level.equalsIgnoreCase("chromosomelevel")) {
437    //                    return this.getChromosomeLevelCoordSystem();
438    //                } else if (level.equalsIgnoreCase("sequencelevel")) {
439    //                    return this.getSequenceLevelCoordSystem();
440    //                }
441                }
442    
443            return null;
444        }
445    
446        @Override
447        public DACoordinateSystem getCSByID(Species species, Integer id) throws DAOException{
448    
449            if (species == null || collection ==null || !this.collection.getSpecies().contains(species)
450                    || id == null) {
451                return null;
452            }
453    
454            DACoordinateSystem out = null;
455            if (!this.CSHash.containsKey(species)) {
456    
457                    //lazyload can throw DAOException
458                    this.lazyLoadCoordinateSytems((DBCollectionSpecies) species);
459    
460            }
461    
462            out = this.CSHash.get(species).get(id); 
463    
464            return out;
465        }
466    
467        @Override
468        public DAChromosome getChromosomeByName(Species species, String name) throws DAOException {
469    
470            if (species == null || collection ==null || !this.collection.getSpecies().contains(species)) {
471                return null;
472            }
473    
474            return this.getCoreFactory(species).getChromosomeDAO().getChromosomeByName(name);
475    
476        }
477    
478        @Override
479        public List<DAChromosome> getChromosomes(Species species) throws DAOException {
480    
481            if (species == null || collection ==null || !this.collection.getSpecies().contains(species)) {
482                return null;
483            }
484    
485            return this.getCoreFactory(species).getChromosomeDAO().getChromosomes();
486    
487        }
488    
489    
490    }