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.coreaccess; 022 023 import uk.ac.roslin.ensembl.datasourceaware.core.DACoordinateSystem; 024 import java.util.ArrayList; 025 import java.util.List; 026 import java.util.HashMap; 027 import org.apache.ibatis.session.SqlSession; 028 import uk.ac.roslin.ensembl.biojava3.EnsemblDNASequenceReader; 029 import uk.ac.roslin.ensembl.dao.coreaccess.DNASequenceDAO; 030 import uk.ac.roslin.ensembl.datasourceaware.core.DAAssembledDNASequence; 031 import uk.ac.roslin.ensembl.datasourceaware.core.DAChromosome; 032 import uk.ac.roslin.ensembl.datasourceaware.core.DADNASequence; 033 import uk.ac.roslin.ensembl.mapper.handler.DBResultHandler; 034 import uk.ac.roslin.ensembl.dao.database.factory.DBDAOCollectionCoreFactory; 035 import uk.ac.roslin.ensembl.dao.database.factory.DBDAOSingleSpeciesCoreFactory; 036 import uk.ac.roslin.ensembl.mapper.core.SequenceMapper; 037 import uk.ac.roslin.ensembl.exception.DAOException; 038 import uk.ac.roslin.ensembl.model.core.DNASequence; 039 import uk.ac.roslin.ensembl.config.EnsemblCoordSystemType; 040 import uk.ac.roslin.ensembl.dao.factory.DAOCollectionCoreFactory; 041 import uk.ac.roslin.ensembl.dao.factory.DAOSingleSpeciesCoreFactory; 042 import uk.ac.roslin.ensembl.model.core.CoordinateSystem; 043 044 /** 045 * 046 * @author paterson 047 */ 048 public class DBDNASequenceDAO extends DBCoreObjectDAO implements DNASequenceDAO{ 049 050 public DBDNASequenceDAO() { 051 super(); 052 } 053 054 public DBDNASequenceDAO(DAOSingleSpeciesCoreFactory factory) { 055 super(factory); 056 } 057 058 public DBDNASequenceDAO(DAOCollectionCoreFactory factory) { 059 super(factory); 060 } 061 062 @Override 063 public String getSequenceByStartStop(EnsemblDNASequenceReader reader, Integer start, Integer stop) throws DAOException { 064 065 066 if (reader==null || reader.getSeqRegionID()==null) { 067 throw new DAOException("Invalid parameter handed to getSequenceByStartStop(EnsemblDNASequenceReader reader, Integer start, Integer stop)"); 068 } 069 070 String out = null; 071 072 Integer id = reader.getSeqRegionID(); 073 Integer begin = start; 074 Integer end = stop; 075 076 HashMap parameters = new HashMap(); 077 parameters.put("id", id); 078 079 SqlSession session = null; 080 081 try { 082 session = this.getFactory().getNewSqlSession(); 083 SequenceMapper mapper = session.getMapper(SequenceMapper.class); 084 085 if (stop ==null && start ==null) { 086 out = mapper.getSequence(parameters); 087 } else if (stop==null && start != null) { 088 parameters.put("start", begin); 089 out = mapper.getSequenceStart(parameters); 090 } else { 091 parameters.put("start", begin); 092 parameters.put("stop", end); 093 out = mapper.getSequenceStartStop(parameters); 094 } 095 096 097 098 } catch (Exception e) { 099 throw new DAOException("Failed to call getSequenceByStartStop", e); 100 } finally { 101 if (session != null) { 102 session.close(); 103 } 104 } 105 106 return out; 107 } 108 109 110 @Override 111 public String getFullSequence(EnsemblDNASequenceReader reader) throws DAOException { 112 return this.getSequenceByStartStop(reader, null, null); 113 } 114 115 @Override 116 public DADNASequence getSequenceByID(Integer id) throws DAOException { 117 118 if (id==null ) { 119 throw new DAOException("Invalid parameter handed to getSequenceByID(Integer id)"); 120 } 121 122 DADNASequence seq = null; 123 124 HashMap parameters = new HashMap(); 125 List<HashMap> results = null; 126 parameters.put("id", id); 127 128 SequenceRowHandler handler = null; 129 SqlSession session = null; 130 131 try { 132 session = this.getFactory().getNewSqlSession(); 133 SequenceMapper mapper = session.getMapper(SequenceMapper.class); 134 results = mapper.getSequenceByID(parameters); 135 } catch (Exception e) { 136 throw new DAOException("Failed to call getSequenceByID", e); 137 } finally { 138 if (session != null) { 139 session.close(); 140 } 141 } 142 143 if (results ==null || results.isEmpty()) { 144 return null; 145 } 146 147 handler = new SequenceRowHandler(results); 148 handler.handleResult(); 149 seq = handler.getObjectResult(); 150 151 152 return seq; 153 } 154 155 @Override 156 public DADNASequence getValidatedSequence(DNASequence seq) throws DAOException { 157 158 if (seq==null || seq.getId()==null) { 159 return null; 160 } 161 162 if ( !(seq instanceof DADNASequence) ) { 163 throw new DAOException("Illegal attempt to validate a non DA sequence "); 164 } 165 166 DADNASequence inseq = (DADNASequence) seq; 167 List<HashMap> results = null; 168 169 DADNASequence newSeq = null; 170 171 HashMap parameters = new HashMap(); 172 parameters.put("id", inseq.getId()); 173 174 SequenceRowHandler handler = null; 175 SqlSession session = null; 176 177 try { 178 session = this.getFactory().getNewSqlSession(); 179 SequenceMapper mapper = session.getMapper(SequenceMapper.class); 180 results = mapper.getSequenceByID(parameters); 181 } catch (Exception e) { 182 throw new DAOException("Failed to call getValidatedSequence", e); 183 } finally { 184 if (session != null) { 185 session.close(); 186 } 187 } 188 189 if (results ==null || results.isEmpty()) { 190 //this punts back the original sequence - ie it has not been validated 191 //so would probably be the wrong behavious 192 //return inseq; 193 return null; 194 } 195 196 handler = new SequenceRowHandler(results); 197 handler.handleResult(); 198 newSeq = handler.getObjectResult(); 199 200 if (newSeq==null) { 201 //this punts back the original sequence - ie it has not been validated 202 //so would probably be the wrong behavious 203 //return inseq; 204 return null; 205 } 206 207 //if object is a DAChromosome, that will be the cached version, 208 //so return it 209 if (newSeq instanceof DAChromosome) { 210 return newSeq; 211 } 212 213 //if the objects are same class, re-intitialize the original 214 if (inseq.getClass().equals(newSeq.getClass()) ) { 215 216 inseq.setDBSeqLength(newSeq.getDBSeqLength()); 217 inseq.setCoordSystem(newSeq.getCoordSystem()); 218 inseq.setName(newSeq.getName()); 219 220 return inseq; 221 222 } 223 //otherwise retrun the new object 224 else { 225 //beware may want to copy some data from inseq to newSeq 226 return newSeq; 227 } 228 229 230 } 231 232 233 @Override 234 public List<? extends DNASequence> getValidatedSequences(List<? extends DNASequence> in_sequences) throws DAOException { 235 236 List<DADNASequence> out_sequences = new ArrayList<DADNASequence>(); 237 238 if (in_sequences==null || in_sequences.isEmpty()) { 239 return out_sequences; 240 } 241 242 List<HashMap> results = null; 243 List<DADNASequence> retrievedSeqs = null; 244 List<Integer> outIDs = new ArrayList(); 245 246 // make a map of the incoming sequences that are to be validated (that have an id) 247 HashMap<Integer, DNASequence> in_idHash = new HashMap<Integer, DNASequence>(); 248 for (DNASequence s: in_sequences ) { 249 if (s.getId()!= null //&& s instanceof DADNASequence 250 ) { 251 in_idHash.put(s.getId(), s); 252 } 253 } 254 255 256 //if we dont have any sequences to validate - return empty list 257 if (in_idHash.isEmpty() || in_idHash.keySet().isEmpty() ) { 258 return out_sequences; 259 } 260 261 List<Integer> in_ids = new ArrayList<Integer>() {}; 262 263 for (Integer i: in_idHash.keySet()) { 264 in_ids.add(i); 265 } 266 267 HashMap parameters = new HashMap(); 268 parameters.put("ids", in_ids); 269 270 SequenceRowHandler handler = null; 271 SqlSession session = null; 272 273 try { 274 session = this.getFactory().getNewSqlSession(); 275 SequenceMapper mapper = session.getMapper(SequenceMapper.class); 276 results = mapper.getSequenceByID(parameters); 277 } catch (Exception e) { 278 throw new DAOException("Failed to call getValidatedSequences", e); 279 } finally { 280 if (session != null) { 281 session.close(); 282 } 283 } 284 285 if (results ==null || results.isEmpty()) { 286 return in_sequences; 287 } 288 289 handler = new SequenceRowHandler(results); 290 handler.handleResult(); 291 retrievedSeqs = handler.getListResult(); 292 293 294 if (retrievedSeqs == null || retrievedSeqs.isEmpty() ) { 295 return in_sequences; 296 } 297 298 299 for (DADNASequence newSeq : retrievedSeqs) { 300 301 //if object is a DAChromosome, that will be the cached version, 302 //so use it 303 if (newSeq instanceof DAChromosome) { 304 out_sequences.add(newSeq); 305 outIDs.add(newSeq.getId()); 306 } 307 308 309 else if (in_idHash.get(newSeq.getId()).getClass().equals(newSeq.getClass())) { 310 311 //if the new sequence is just the same type as the original 312 //just modify the original and use it in the reretruned List 313 in_idHash.get(newSeq.getId()).setDBSeqLength(newSeq.getDBSeqLength()); 314 in_idHash.get(newSeq.getId()).setCoordSystem(newSeq.getCoordSystem()); 315 in_idHash.get(newSeq.getId()).setName(newSeq.getName()); 316 try { 317 out_sequences.add((DADNASequence) in_idHash.get(newSeq.getId())); 318 outIDs.add(newSeq.getId()); 319 } catch (ClassCastException cce) { } 320 321 } 322 323 324 else { 325 326 //if the new sequence is a subclass, use it in the return List 327 //beware - we may need to copy other properties fromold to new 328 out_sequences.add(newSeq); 329 outIDs.add(newSeq.getId()); 330 331 } 332 333 334 } 335 336 // ADD BACK any input sequences that werent pulled back from database 337 for (Integer i : in_idHash.keySet()) { 338 if (!outIDs.contains(i)) { 339 try { 340 out_sequences.add((DADNASequence) in_idHash.get(i)); 341 outIDs.add(i); 342 } catch (ClassCastException cce) { } 343 } 344 } 345 346 return out_sequences; 347 348 } 349 350 351 352 353 //*********************************************** 354 355 356 public class SequenceRowHandler implements DBResultHandler { 357 358 // the magic strings to be used as property keys for HashMap in Ibatis 359 private final String id = "id"; 360 private final String name = "name"; 361 private final String length = "length"; 362 private final String coordSystemID = "csID"; 363 private List<HashMap> rawResults = null; 364 365 //this may be a subclass according to type 366 private DADNASequence objectResult = null; 367 368 369 private List<DADNASequence> listResult = new ArrayList<DADNASequence>(); 370 371 public SequenceRowHandler(List<HashMap> results) { 372 rawResults = results; 373 } 374 375 376 @Override 377 public List<DADNASequence> getListResult() { 378 return listResult; 379 } 380 381 @Override 382 public DADNASequence getObjectResult() { 383 return objectResult; 384 } 385 386 public void handleResult() throws DAOException { 387 388 if (rawResults == null || rawResults.isEmpty()) { 389 return; 390 } 391 392 for (HashMap map : rawResults) { 393 handleRow(map); 394 } 395 396 } 397 398 399 private void handleRow(HashMap result) throws DAOException { 400 401 402 if (result == null || result.isEmpty()) { 403 return; 404 } 405 406 DADNASequence rowSequence = null; 407 408 rowSequence = this.parseResult(result); 409 410 411 if (rowSequence!= null) { 412 this.objectResult = rowSequence; 413 this.listResult.add((DADNASequence) rowSequence); 414 } 415 416 } 417 418 419 private DADNASequence parseResult(HashMap result) throws DAOException { 420 421 if (result == null) { 422 return null; 423 } 424 425 DADNASequence pseq = null; 426 Integer length = null; 427 Integer id = null; 428 Integer pcsID = null; 429 String name = null; 430 CoordinateSystem cs = null; 431 432 433 pcsID = (Integer) result.get(this.coordSystemID); 434 length = (Integer) result.get(this.length); 435 id = (Integer) result.get(this.id); 436 name = (String) result.get(this.name); 437 438 439 if(singleSpecies) { 440 cs = ssFactory.getDatabase().getCSByID(pcsID); 441 } else { 442 cs= collFactory.getDatabase().getCSByID(species, pcsID); 443 } 444 445 446 if (cs.getType()==EnsemblCoordSystemType.chromosome ) { 447 pseq = new DAChromosome(); 448 } else if (! cs.isSequenceLevel()) { 449 pseq = new DAAssembledDNASequence(); 450 } else { 451 pseq = new DADNASequence(); 452 } 453 454 455 pseq.setId(id); 456 pseq.setCoordSystem(cs); 457 pseq.setDBSeqLength(length); 458 pseq.setName(name); 459 pseq.setDaoFactory(daoFactory); 460 461 //do check for cached chromosomes here 462 if (pseq instanceof DAChromosome) 463 { 464 pseq = species.getCachedChromosome((DAChromosome)pseq); 465 } 466 467 return pseq; 468 469 470 } 471 } 472 473 }