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 java.util.logging.Level; 030 import java.util.logging.Logger; 031 import uk.ac.roslin.ensembl.datasourceaware.core.DAChromosome; 032 import uk.ac.roslin.ensembl.dao.database.factory.DBDAOSingleSpeciesCoreFactory; 033 import uk.ac.roslin.ensembl.dao.database.factory.DBDAOSingleSpeciesFactory; 034 import uk.ac.roslin.ensembl.exception.ConfigurationException; 035 import uk.ac.roslin.ensembl.exception.DAOException; 036 import uk.ac.roslin.ensembl.config.EnsemblDBType; 037 import uk.ac.roslin.ensembl.datasourceaware.core.DACoordinateSystem; 038 import uk.ac.roslin.ensembl.model.ObjectType; 039 import uk.ac.roslin.ensembl.model.core.CoordinateSystem; 040 import uk.ac.roslin.ensembl.model.database.SingleSpeciesCoreDatabase; 041 import uk.ac.roslin.ensembl.config.EnsemblCoordSystemType; 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 DBSingleSpeciesCoreDatabase extends DBSingleSpeciesDatabase implements SingleSpeciesCoreDatabase { 050 051 private List<DACoordinateSystem> coordSystems = new ArrayList<DACoordinateSystem>(); 052 private TreeMap<Integer, DACoordinateSystem> rankedCoordSystemsHash = new TreeMap<Integer, DACoordinateSystem>(); 053 private TreeMap<Integer, DACoordinateSystem> idCoordSystemsHash = new TreeMap<Integer, DACoordinateSystem>(); 054 private Integer chromosomeLevelID = null; 055 private Integer sequenceLevelID = null; 056 private Integer topLevelID = null; 057 private DACoordinateSystem chromosomeLevelCS = null; 058 private DACoordinateSystem sequenceLevelCS = null; 059 private DACoordinateSystem topLevelCS = null; 060 private HashMap<FeatureType, String> defaultBuildLevels = new HashMap<FeatureType, String>(); 061 private HashMap<FeatureType, HashMap<DACoordinateSystem, Integer>> featureCSHash = null; 062 private HashMap<DACoordinateSystem, List<FeatureType>> CSFeatureHash = null; 063 064 public DBSingleSpeciesCoreDatabase(String db_name, EnsemblDBType type, Registry registry) throws ConfigurationException { 065 super(db_name, type, registry); 066 } 067 068 @Override 069 public DBDAOSingleSpeciesCoreFactory getCoreFactory() { 070 if (this.factory == null) { 071 try { 072 this.factory = DBDAOSingleSpeciesFactory.makeFactory(this); 073 } catch (Exception ex) { 074 } 075 } 076 077 if (this.factory != null) { 078 return (DBDAOSingleSpeciesCoreFactory) this.factory; 079 } else { 080 return null; 081 } 082 } 083 084 085 private List<DACoordinateSystem> fetchCS() throws DAOException { 086 List<DACoordinateSystem> coords = new ArrayList<DACoordinateSystem>(); 087 //can throw DAOException 088 if ( this.getCoreFactory()!=null) { 089 coords = this.getCoreFactory().getCoordinateSystemDAO(). 090 getCoordinateSystems(); 091 } else { 092 return coords; 093 } 094 return coords; 095 } 096 097 private void setCoordinateSytems(List<DACoordinateSystem> coords) throws DAOException { 098 099 this.coordSystems.clear(); 100 this.coordSystems.addAll(coords); 101 102 //set the ids for the top, chromosome and sequence levels 103 104 for (DACoordinateSystem cs : coordSystems) { 105 106 this.rankedCoordSystemsHash.put(cs.getRank(), cs); 107 this.idCoordSystemsHash.put(cs.getId(), cs); 108 109 if (cs.getRank().equals(1)) { 110 this.topLevelCS = cs; 111 this.topLevelID = cs.getId(); 112 if (cs.getType() == EnsemblCoordSystemType.chromosome) { 113 this.chromosomeLevelCS = cs; 114 this.chromosomeLevelID = cs.getId(); 115 } 116 } 117 118 if (cs.isSequenceLevel()) { 119 this.sequenceLevelCS = cs; 120 this.sequenceLevelID = cs.getId(); 121 } 122 } 123 124 //if the top rank wasnt chromosome level, find the highest ranked chromosome level 125 126 if (this.chromosomeLevelID == null) { 127 128 129 Iterator<Integer> it = this.rankedCoordSystemsHash.keySet().iterator(); 130 while (it.hasNext()) { 131 DACoordinateSystem cs = this.rankedCoordSystemsHash.get(it.next()); 132 if (cs.getType() == EnsemblCoordSystemType.chromosome) { 133 this.chromosomeLevelID = cs.getId(); 134 break; 135 } 136 } 137 } 138 139 140 } 141 142 private void lazyLoadCoordinateSytems() throws DAOException { 143 144 this.coordSystems.clear(); 145 146 List<DACoordinateSystem> coords = this.fetchCS(); 147 148 if (!coords.isEmpty()) { 149 this.setCoordinateSytems(coords); 150 } 151 152 //set nil values to prevent repeating lazy load 153 154 if (this.chromosomeLevelID == null) { 155 this.chromosomeLevelID = 0; 156 } 157 if (this.topLevelID == null) { 158 this.topLevelID = 0; 159 } 160 if (this.sequenceLevelID == null) { 161 this.sequenceLevelID = 0; 162 } 163 164 } 165 166 @Override 167 public DACoordinateSystem getCSByID(Integer id) throws DAOException { 168 DACoordinateSystem out = null; 169 if (topLevelID == null && this.coordSystems.isEmpty()) { 170 171 //lazyload can throw DAOException 172 lazyLoadCoordinateSytems(); 173 174 } 175 176 out = this.idCoordSystemsHash.get(id); 177 178 return out; 179 } 180 181 @Override 182 public DACoordinateSystem getTopLevelCoordSystem() throws DAOException { 183 if (topLevelID == null && this.coordSystems.isEmpty()) { 184 //lazyload can throw DAOException 185 lazyLoadCoordinateSytems(); 186 } 187 return topLevelCS; 188 } 189 190 @Override 191 public DACoordinateSystem getChromosomeLevelCoordSystem() throws DAOException { 192 if (chromosomeLevelID == null && this.coordSystems.isEmpty()) { 193 //lazyload can throw DAOException 194 lazyLoadCoordinateSytems(); 195 } 196 return chromosomeLevelCS; 197 } 198 199 @Override 200 public DACoordinateSystem getSequenceLevelCoordSystem() throws DAOException { 201 if (sequenceLevelID == null && this.coordSystems.isEmpty()) { 202 //lazyload can throw DAOException 203 lazyLoadCoordinateSytems(); 204 } 205 return sequenceLevelCS; 206 } 207 208 @Override 209 public DAChromosome getChromosomeByName(String name) throws DAOException { 210 if (this.getCoreFactory()!=null){ 211 return this.getCoreFactory().getChromosomeDAO().getChromosomeByName(name); 212 } else { 213 return null; 214 } 215 216 } 217 218 @Override 219 public List<DAChromosome> getChromosomes() throws DAOException { 220 if (this.getCoreFactory()!=null){ 221 return this.getCoreFactory().getChromosomeDAO().getChromosomes(); 222 } else { 223 return new ArrayList<DAChromosome>(); 224 } 225 } 226 227 private void setFeatureCSHash() throws DAOException { 228 229 if (sequenceLevelID == null && this.coordSystems.isEmpty()) { 230 //lazyload can throw DAOException 231 lazyLoadCoordinateSytems(); 232 } 233 234 featureCSHash = new HashMap<FeatureType, HashMap<DACoordinateSystem, Integer>>(); 235 CSFeatureHash = new HashMap<DACoordinateSystem, List<FeatureType>>(); 236 237 for (DACoordinateSystem c : this.coordSystems) { 238 CSFeatureHash.put(c, new ArrayList<FeatureType>()); 239 240 } 241 242 243 if (this.getCoreFactory() != null) { 244 245 try { 246 247 this.getCoreFactory().getCoordinateSystemDAO().setFeatureCS(); 248 249 } catch (DAOException e) { 250 featureCSHash = null; 251 CSFeatureHash = null; 252 throw e; 253 } 254 } 255 256 } 257 258 @Override 259 public Set<DACoordinateSystem> getCSForFeature(ObjectType featureType) throws DAOException { 260 261 if (this.featureCSHash == null) { 262 this.setFeatureCSHash(); 263 } 264 265 266 if (this.featureCSHash != null 267 && this.featureCSHash.containsKey(featureType)) { 268 return this.featureCSHash.get(featureType).keySet(); 269 } else { 270 271 return null; 272 } 273 } 274 275 @Override 276 public List<FeatureType> getFeaturesForCS(CoordinateSystem coordSys) throws DAOException{ 277 278 279 if (this.featureCSHash == null) { 280 this.setFeatureCSHash(); 281 } 282 283 284 if (this.CSFeatureHash != null 285 && this.CSFeatureHash.containsKey(coordSys)) { 286 return this.CSFeatureHash.get(coordSys); 287 } else { 288 return null; 289 } 290 } 291 292 @Override 293 public Integer getMaxLengthForFeature(ObjectType featureType, CoordinateSystem cs) throws DAOException { 294 295 if ( featureType == null || cs == null ) { 296 return null; 297 } 298 299 if (this.featureCSHash == null) { 300 this.setFeatureCSHash(); 301 } 302 303 304 305 if (this.featureCSHash != null 306 && this.featureCSHash.containsKey(featureType) 307 && this.featureCSHash.get(featureType).containsKey(cs)) { 308 return this.featureCSHash.get(featureType).get(cs); 309 } else { 310 return null; 311 } 312 313 } 314 315 @Override 316 public void addFeatureCS(String featureType, Integer csID, Integer maxLength) { 317 318 FeatureType type = null; 319 DACoordinateSystem cs = null; 320 321 type = FeatureType.getFeatureType(featureType); 322 cs = this.idCoordSystemsHash.get(csID); 323 324 if (type == null || cs == null) { 325 return; 326 } else { 327 if (!this.featureCSHash.containsKey(type)) { 328 this.featureCSHash.put(type, new HashMap<DACoordinateSystem, Integer>()); 329 } 330 this.featureCSHash.get(type).put(cs, maxLength); 331 332 this.CSFeatureHash.get(cs).add(type); 333 334 } 335 336 337 } 338 339 @Override 340 public void setBuildLevel(String featureKey, String level) { 341 String temp = featureKey.replace("build.level", ""); 342 343 if (FeatureType.getFeatureType(temp) != null) { 344 this.defaultBuildLevels.put(FeatureType.getFeatureType(temp), level); 345 } 346 } 347 348 @Override 349 public String getBuildLevel(String featureType) throws DAOException{ 350 if (FeatureType.getFeatureType(featureType) != null) { 351 if (defaultBuildLevels.isEmpty()) { 352 this.getRegistry().setCoreDBBuildLevels(this); 353 } 354 return this.defaultBuildLevels.get(FeatureType.getFeatureType(featureType)); 355 } else { 356 return null; 357 } 358 } 359 360 @Override 361 public DACoordinateSystem getBuildCoordSystem(String featureType) throws DAOException { 362 363 if (FeatureType.getFeatureType(featureType) != null) { 364 if (defaultBuildLevels.isEmpty()) { 365 this.getRegistry().setCoreDBBuildLevels(this); 366 } 367 String level = this.defaultBuildLevels.get(FeatureType.getFeatureType(featureType)); 368 if (level != null && level.equalsIgnoreCase("toplevel")) { 369 return this.getTopLevelCoordSystem(); 370 } else { 371 return null; 372 } 373 374 // //are there other values possible? 375 // else if (level.equalsIgnoreCase("chromosomelevel")) { 376 // return this.getChromosomeLevelCoordSystem(); 377 // } else if (level.equalsIgnoreCase("sequencelevel")) { 378 // return this.getSequenceLevelCoordSystem(); 379 // } 380 } 381 382 return null; 383 384 } 385 386 //dont really want this public - just for testing 387 public HashMap<FeatureType, String> getBuildLevels() { 388 if (defaultBuildLevels.isEmpty()) { 389 try { 390 lazyLoadCoordinateSytems(); 391 } catch (DAOException ex) { 392 393 } 394 } 395 return defaultBuildLevels; 396 } 397 }