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.coreaccess; 023 024import java.util.ArrayList; 025import java.util.HashMap; 026import java.util.List; 027import org.apache.ibatis.session.SqlSession; 028import org.slf4j.Logger; 029import org.slf4j.LoggerFactory; 030import uk.ac.roslin.ensembl.config.DBConnection.DataSource; 031import uk.ac.roslin.ensembl.config.EnsemblComparaDivision; 032import uk.ac.roslin.ensembl.config.EnsemblCoordSystemType; 033import uk.ac.roslin.ensembl.config.FeatureType; 034import uk.ac.roslin.ensembl.dao.coreaccess.GeneDAO; 035import uk.ac.roslin.ensembl.dao.database.DBCollectionSpecies; 036import uk.ac.roslin.ensembl.dao.factory.DAOCollectionCoreFactory; 037import uk.ac.roslin.ensembl.dao.factory.DAOCoreFactory; 038import uk.ac.roslin.ensembl.dao.factory.DAOSingleSpeciesCoreFactory; 039import uk.ac.roslin.ensembl.datasourceaware.DAXRef; 040import uk.ac.roslin.ensembl.datasourceaware.core.DAAssembledDNASequence; 041import uk.ac.roslin.ensembl.datasourceaware.core.DAChromosome; 042import uk.ac.roslin.ensembl.datasourceaware.core.DADNASequence; 043import uk.ac.roslin.ensembl.datasourceaware.core.DAGene; 044import uk.ac.roslin.ensembl.exception.DAOException; 045import uk.ac.roslin.ensembl.mapper.core.GeneMapper; 046import uk.ac.roslin.ensembl.mapper.handler.DBResultHandler; 047import uk.ac.roslin.ensembl.mapper.handler.HashMapHolder; 048import uk.ac.roslin.ensembl.mapper.query.FeatureQuery; 049import uk.ac.roslin.ensembl.model.Coordinate; 050import uk.ac.roslin.ensembl.model.IdentifiableObject; 051import uk.ac.roslin.ensembl.model.Mapping; 052import uk.ac.roslin.ensembl.model.core.CollectionSpecies; 053import uk.ac.roslin.ensembl.model.core.CoordinateSystem; 054import uk.ac.roslin.ensembl.model.core.CoreObject; 055import uk.ac.roslin.ensembl.model.core.DNASequence; 056 057 058public class DBGeneDAO extends DBCoreObjectDAO implements GeneDAO { 059 060 //if the meta table tells us that genebuild.level is 'toplevel' 061 //we can grab the top ranked CS and use this for all genes 062 //there may be other values than 'toplevel' - i dont know what :) 063 //if the build level isn't annotated we have to get the possible CS levels 064 //from meta_coord and use which ever one is approriate! 065 CoordinateSystem geneBuildCS = null; 066 final static Logger LOGGER = LoggerFactory.getLogger(DBGeneDAO.class); 067 068 069 public DBGeneDAO() { 070 super(); 071 } 072 073 public DBGeneDAO(DAOSingleSpeciesCoreFactory factory) throws DAOException { 074 super(factory); 075 076 //we want to initialize the GeneDAO so that it knows which COordinate system 077 //it needs to quwery about genes 078 079 geneBuildCS = this.ssFactory.getDatabase().getBuildCoordSystem(FeatureType.gene.toString()); 080 //what if this is null or throws an exception? 081 //if it throws an exception we are probably in some sort of bad factory environment 082 if (geneBuildCS==null) { 083 geneBuildCS=this.ssFactory.getDatabase().getTopLevelCoordSystem(); 084 } 085 } 086 087 public DBGeneDAO(DAOCollectionCoreFactory factory) throws DAOException { 088 super(factory); 089 geneBuildCS= this.collFactory.getDatabase().getBuildCoordSystem(species, FeatureType.gene.toString()); 090 //what if this is null or throw an exception? 091 //if it throws an exception we are probably in some sorto f baf dfactory environment 092 if (geneBuildCS==null) { 093 geneBuildCS=this.collFactory.getDatabase().getTopLevelCS(species); 094 } 095 } 096 097 /** 098 * Uses the stableid of an object to fill in missing data that would have been 099 * present if the the gene had intially been made by a call to getGeneByStableID 100 * or getGeneByID. 101 * @param object 102 * @throws DAOException 103 */ 104 @Override 105 public void reInitialize(IdentifiableObject object) throws DAOException { 106 107 if (object == null || !(object instanceof DAGene)) { 108 throw new DAOException("Object not a DAGene"); 109 } 110 111 DAGene gene = (DAGene) object; 112 113 //the DAO method requires a stableID 114 if (gene.getStableID() == null || gene.getStableID().isEmpty()) { 115 return; 116 } 117 118 DAGene temp = this.getGeneByStableID(gene.getStableID()); 119 120 if (temp != null) { 121 gene.setAnalysisID(temp.getAnalysisID()); 122 gene.setDisplayXRef(temp.getDisplayXRef()); 123 gene.setBiotype(temp.getBiotype()); 124 gene.setId(temp.getId()); 125 gene.setCanonicalTranscriptID(temp.getCanonicalTranscriptID()); 126 gene.setCreationDate(temp.getCreationDate()); 127 gene.setModificationDate(temp.getModificationDate()); 128 gene.setDescription(temp.getDescription()); 129 gene.setCurrent(temp.isCurrent()); 130 gene.setDisplayName(temp.getDisplayName()); 131 gene.setStatus(temp.getStatus()); 132 gene.setVersion(temp.getVersion()); 133 gene.setHomoeologueCount(temp.getHomoeologueCount()); 134 gene.setOrthologueCount(temp.getOrthologueCount()); 135 gene.setParalogueCount(temp.getParalogueCount()); 136 137 for (Mapping tempMapping : temp.getLoadedMappings()) { 138 Mapping tempRevMapping = tempMapping.getReverseMapping(); 139 if (tempRevMapping != null) { 140 tempRevMapping.setTarget(gene); 141 } 142 tempMapping.setSource(gene); 143 gene.addMapping(tempMapping); 144 145// Mapping mapping = new Mapping(); 146// mapping.setSource(gene); 147// mapping.setTargetCoordinates(tempMapping.getTargetCoordinates()); 148//// m.getTarget().clearAllMappings(); 149// mapping.setTarget(tempMapping.getTarget()); 150// if (gene.addMapping(mapping)) { 151// Mapping.addReverseMapping(mapping); 152// } 153 } 154 } 155 gene.setInitialized(true); 156 } 157 158 /** 159 * @param id 160 * 161 * @throws DAOException 162 */ 163 @Override 164 public DAGene getGeneByID(Integer id) throws DAOException { 165 166 if (id==null) { 167 return null; 168 } 169 170 FeatureQuery q = new FeatureQuery(); 171 q.setFeatureID(id); 172 if (!singleSpecies) { 173 try { 174 q.setSpeciesID(species.getDBSpeciesID(this.getFactory().getDBVersion())); 175 } catch (Exception e) { 176 throw new DAOException("No species ID context for this query!", e); 177 } 178 } 179 180 String comparaDB = this.getComparaDB(); 181 if (comparaDB!=null && !comparaDB.isEmpty()) { 182 q.setComparaDB(comparaDB); 183 } 184 return this.getGene(q); 185 } 186 187 @Override 188 public DAGene addGeneByIDOnParent(Integer id, DNASequence parent) throws DAOException { 189 if (parent == null || !(parent instanceof DADNASequence) || ((CoreObject) parent).getId() == null) { 190 throw new DAOException("No valid parent DNA provided"); 191 } 192 if (id == null ) { 193 return null; 194 } 195 FeatureQuery q = new FeatureQuery(); 196 if (!singleSpecies) { 197 try { 198 q.setSpeciesID(species.getDBSpeciesID(this.getFactory().getDBVersion())); 199 } catch (Exception e) { 200 throw new DAOException("No species ID context for this query!", e); 201 } 202 } 203 q.setFeatureID(id); 204 //this is redundant - if the rowGene doesnt map on this sequence 205 //adding this parameter or not we would still get no genes back 206 //adding this parameter has the effect of 207 //making this a different query to getGeneByID and therefore 208 //will return a differnt object - not a cached one 209 q.setParentSequenceID(parent.getId()); 210 211 if (Integer.parseInt(this.getDAOFactory().getEnsemblSchemaVersion()) > 75) { 212 String comparaDB = this.getComparaDB(); 213 if (comparaDB != null && !comparaDB.isEmpty()) { 214 q.setComparaDB(comparaDB); 215 } 216 } 217 return this.getGeneOnParent(q, (DADNASequence) parent); 218 } 219 220 /** 221 * @param stableID 222 * 223 * @throws DAOException 224 */ 225 @Override 226 public DAGene getGeneByStableID(String stableID) throws DAOException { 227 if (stableID==null || stableID.isEmpty() ) { 228 return null; 229 } 230 231 FeatureQuery q = new FeatureQuery(); 232 if (!singleSpecies) { 233 try { 234 q.setSpeciesID(species.getDBSpeciesID(this.getFactory().getDBVersion())); 235 } catch (Exception e) { 236 throw new DAOException("No species ID context for this query!", e); 237 } 238 } 239 q.setFeatureStableID(stableID.trim()); 240 241 if (Integer.parseInt(this.getDAOFactory().getEnsemblSchemaVersion()) > 75) { 242 String comparaDB = this.getComparaDB(); 243 if (comparaDB != null && !comparaDB.isEmpty()) { 244 q.setComparaDB(comparaDB); 245 } 246 } 247 248 return this.getGene(q); 249 } 250 251 /** 252 * The gene returned has mapping to a sequence region - and the id for 253 * the coordinate system that this region belongs to 254 * @param stableID 255 * @param parent 256 * 257 * @throws DAOException 258 */ 259 @Override 260 public DAGene addGeneByStableIDOnParent(String stableID, DNASequence parent) throws DAOException { 261 if (parent == null || !(parent instanceof DADNASequence) || ((CoreObject) parent).getId() == null) { 262 throw new DAOException("No valid parent DNA provided"); 263 } 264 if (stableID == null || stableID.isEmpty() ) { 265 return null; 266 } 267 FeatureQuery q = new FeatureQuery(); 268 if (!singleSpecies) { 269 try { 270 q.setSpeciesID(species.getDBSpeciesID(this.getFactory().getDBVersion())); 271 } catch (Exception e) { 272 throw new DAOException("No species ID context for this query!", e); 273 } 274 } 275 q.setFeatureStableID(stableID.trim()); 276 //this is redundant - if the rowGene doesnt map on this sequence 277 //adding this parameter or not we would still get no genes back 278 //adding this parameter has the effect of 279 //making this a different query to getGeneByID and therefore 280 //will return a differnt object - not a cached one 281 q.setParentSequenceID(parent.getId()); 282 if (Integer.parseInt(this.getDAOFactory().getEnsemblSchemaVersion()) > 75) { 283 String comparaDB = this.getComparaDB(); 284 if (comparaDB != null && !comparaDB.isEmpty()) { 285 q.setComparaDB(comparaDB); 286 } 287 } 288 return this.getGeneOnParent(q, (DADNASequence) parent); 289 } 290 291 @Override 292 public List<Mapping> getGeneMappingsOnRegion(DNASequence region, Coordinate coords) throws DAOException { 293 294 List<Mapping> mappings = new ArrayList<Mapping>(); 295 FeatureQuery q = new FeatureQuery(); 296 if (!singleSpecies) { 297 try { 298 q.setSpeciesID(species.getDBSpeciesID(this.getFactory().getDBVersion())); 299 } catch (Exception e) { 300 throw new DAOException("No species ID context for this query!", e); 301 } 302 } 303 CoordinateSystem cs = null; 304 305 if (region == null || region.getId()==null || region.getCoordSystem()== null ) { 306 throw new DAOException("No valid region or coordinate system specified"); 307 } else { 308 cs = region.getCoordSystem(); 309 q.setParentSequenceID(region.getId()); 310 q.setCoordinateSystemID(cs.getId()); 311 } 312 313 if (coords != null) { 314 q.setParentStart(coords.getStart()); 315 q.setParentStop(coords.getEnd()); 316 } 317 318// //what happens if we dont have a CS?? 319// //do we want to try with the gene build CS is if there is one 320// //this is 'always' toplevel i.e. 1 321// //but the sequence might not be at this level 322// //so we would have to checke this before doing it 323// //probably safest to force a lazy load on sequence.getCoordSystem() 324// //i.e not do this.... 325// else { 326// cs = this.geneBuildCS; 327// //q.setCoordinateSystemID(this.geneBuildCS.getId()); 328// } 329 330 //for maximum length 331 //will need different method if constructed from CollectionDB 332 333 Integer max = null; 334 if (this.singleSpecies) { 335 max= this.ssFactory.getDatabase().getMaxLengthForFeature(FeatureType.gene, this.geneBuildCS); 336 } else { 337 max= this.collFactory.getDatabase().getMaxLengthForFeature((DBCollectionSpecies) species, FeatureType.gene, this.geneBuildCS); 338 } 339 340 if (max != null) { 341 q.setMaximumFeatureLength(max); 342 } 343 if (Integer.parseInt(this.getDAOFactory().getEnsemblSchemaVersion()) > 75) { 344 String comparaDB = this.getComparaDB(); 345 if (comparaDB != null && !comparaDB.isEmpty()) { 346 q.setComparaDB(comparaDB); 347 } 348 } 349 350 //out = this.getGenesOnParent(q, (DADNASequence) region); 351 352 mappings = this.getMappingsOnParent(q, (DADNASequence) region); 353 354 355 // this gets the desired genes filtered by stand if specified 356 // probably should be done in the calling class 357 358// if (coords.getStrand() == null) { 359// for (Mapping m : mappings) { 360// out.add((DAGene) m.getSource()); 361// } 362// } else { 363// for (Mapping m : mappings) { 364// if (m.getTargetCoordinates().getStrand().equals(coords.getStrand())) { 365// out.add((DAGene) m.getSource()); 366// } 367// } 368// } 369 370 return mappings; 371 } 372 373 /** 374 * Returns a list of Ensembl Genes matching the query VegaID string. 375 * Vega currently curates gene, transcript and protein annotations for a human 376 * and and a few key regions of other vertebrate species. Calling this method 377 * on EnsemblGenomes (invertebrate) species will return an empty list by default. 378 * @param id a valid vega ID (these begin 'OTT...') 379 * 380 * @throws DAOException 381 */ 382 @Override 383 public List<DAGene> getGenesForVegaID(String id) throws DAOException { 384 385 //return an empty list rather than null 386 List<DAGene> out = new ArrayList<DAGene>(); 387 388 if (id==null || id.isEmpty() 389 || !this.getFactory().getRegistry().getDatasourceType().equals(DataSource.ENSEMBLDB)) { 390 return out; 391 } 392 393 List<HashMapHolder> l = null; 394 GeneMappingRowHandler handler = null; 395 396 List<HashMap> result = new ArrayList<HashMap>(); 397 398 SqlSession session = null; 399 400 try { 401 session = this.getFactory().getNewSqlSession(); 402 GeneMapper mapper = session.getMapper(GeneMapper.class); 403 l = mapper.getVegaGenes(id); 404 } catch (Exception e) { 405 throw new DAOException("Failed to call getGenesForVegaID", e); 406 } finally { 407 if (session != null) { 408 session.close(); 409 } 410 } 411 if (l != null) { 412 for (HashMapHolder h : l) { 413 414 result.add(h.getMap()); 415 416 } 417 418 if (result != null && !result.isEmpty()) { 419 420 handler = new GeneMappingRowHandler(result); 421 handler.handleResult(); 422 out = handler.getListResult(); 423 } 424 } 425 426 if (out==null) { 427 out = new ArrayList<DAGene>(); 428 } 429 430 /* 431 * NOTE: we dont set the query VegaID on the return gene as this being null 432 * is the trigger for lazyloading a vega XRef. 433 * NOR can we make a valid Vega XRef at this point as we dont have enough information 434 * (ie we dont have its database ID). 435 */ 436 437// if (!out.isEmpty()) { 438// ExternalDB edb = this.daoFactory.getDatabase().getExternalDB(ExternalDBType.VegaGene.toString()); 439// //note the full details of this xref won't be filled in - requiring lazy loading 440// DAXRef xref = new DAXRef(); 441// xref.setDaoFactory(this.getFactory()); 442// xref.setDB(edb); 443// xref.setPrimaryAccession(id); 444// xref.setDisplayID(id); 445// xref.setDBName(edb.getDBName()); 446// 447// for (DAGene g : out) { 448// g.setVegaGeneID(id); 449// g.addTypedXRefs(ExternalDBType.VegaGene, new ArrayList<DAXRef>(Arrays.asList(xref))); 450// } 451// } 452 return out; 453 } 454 455 /* 456 * Looks up any Genes with a display name or XRef synonym matching the query (case insensitive). 457 */ 458 @Override 459 public List<DAGene> getGenesByExactName(String name) throws DAOException { 460 461 //return an empty list rather than null 462 List<DAGene> out = new ArrayList<DAGene>(); 463 if (name==null || name.isEmpty()) { 464 return out; 465 } 466 467 FeatureQuery q = new FeatureQuery(); 468 q.setFeatureName(name); 469 if (!singleSpecies) { 470 try { 471 q.setSpeciesID(species.getDBSpeciesID(this.getFactory().getDBVersion())); 472 } catch (Exception e) { 473 throw new DAOException("No species ID context for this query!", e); 474 } 475 } 476 477 SqlSession session = null; 478 479 try { 480 session = this.getFactory().getNewSqlSession(); 481 GeneMapper mapper = session.getMapper(GeneMapper.class); 482 out = mapper.getGenesByName(q); 483 } catch (Exception e) { 484 throw new DAOException("Failed to call getGenesByName('"+name+"')", e); 485 } finally { 486 if (session != null) { 487 session.close(); 488 } 489 } 490 if (out == null) { 491 return new ArrayList<DAGene>(); 492 } 493 for (DAGene g: out) { 494 g.setDaoFactory(daoFactory); 495 } 496 497 return out; 498 } 499 500 /* 501 * Looks up any Genes with a display name or XRef synonym beginning 502 * with a match to the query (case insensitive). 503 */ 504 @Override 505 public List<DAGene> getGenesByNameBeginning(String name) throws DAOException { 506 return getGenesByExactName(name+"%"); 507 } 508 509 510 //******************************* 511 512 private DAGene getGene(FeatureQuery query) throws DAOException { 513 DAGene out = null; 514 GeneMappingRowHandler handler = null; 515 List<HashMap> result; 516 517 SqlSession session = null; 518 519 try { 520 session = this.getFactory().getNewSqlSession(); 521 GeneMapper mapper = session.getMapper(GeneMapper.class); 522 result = mapper.getGene(query); 523 } catch (Exception e) { 524 throw new DAOException("Failed to call getGene", e); 525 } finally { 526 if (session != null) { 527 session.close(); 528 } 529 } 530 531 if (result != null && !result.isEmpty()) { 532 533 handler = new GeneMappingRowHandler(result); 534 handler.handleResult(); 535 out = handler.getObjectResult(); 536 } 537 538 return out; 539 } 540 541 private DAGene getGeneOnParent(FeatureQuery query, DADNASequence parent) throws DAOException { 542 DAGene out = null; 543 GeneMappingRowHandler handler = null; 544 List<HashMap> result; 545 546 SqlSession session = null; 547 548 try { 549 session = this.getFactory().getNewSqlSession(); 550 GeneMapper mapper = session.getMapper(GeneMapper.class); 551 result = mapper.getGene(query); 552 } catch (Exception e) { 553 throw new DAOException("Failed to call getGeneOnParent", e); 554 } finally { 555 if (session != null) { 556 session.close(); 557 } 558 } 559 560 if (result != null && !result.isEmpty()) { 561 562 handler = new GeneMappingRowHandler(result, parent); 563 handler.handleResult(); 564 out = handler.getObjectResult(); 565 } 566 567 return out; 568 } 569 570 private List<Mapping> getMappingsOnParent(FeatureQuery query, DADNASequence parent) throws DAOException { 571 List<Mapping> out = null; 572 573 MappingRowHandler handler = null; 574 List<HashMap> result; 575 576 SqlSession session = null; 577 578 try { 579 session = this.getFactory().getNewSqlSession(); 580 GeneMapper mapper = session.getMapper(GeneMapper.class); 581 result = mapper.getGene(query); 582 } catch (Exception e) { 583 throw new DAOException("Failed to call getMappingsOnParent", e); 584 } finally { 585 if (session != null) { 586 session.close(); 587 } 588 } 589 590 if (result != null && !result.isEmpty()) { 591 592 handler = new MappingRowHandler(result, parent); 593 handler.handleResult(); 594 out = handler.getListResult(); 595 } 596 597 return out; 598 } 599 600 601 @Override 602 public String getComparaDB() { 603 604 Integer dbVersion = Integer.parseInt(this.getDAOFactory().getDBVersion()); 605 606 //homologies for bacteria after release 16 are only calulated for the species in 607 //pan homology set, adn are only stored in the ensembl_compara_pan_homology db, 608 //not the ensembl_compara_bacteria db. there is no homology data for other species 609 if (species instanceof CollectionSpecies && dbVersion > 16) { 610 if (this.getDAOFactory().getRegistry().isSpeciesInPanHomology(species, this.getDAOFactory().getDBVersion())) { 611 return "ensembl_compara_pan_homology_" + this.getDAOFactory().getDBVersion()+"_"+this.getDAOFactory().getEnsemblSchemaVersion(); 612 } else { 613 return null; 614 } 615 } 616 617 return this.getDAOFactory().getComparaFactory(species.getComparaDivision()).getDatabaseName(); 618 } 619 620 621 //********************************* 622 623 // I haven't decided whether it is better to get theobjects 624 //(with the mappings filled in) 625 // or to get the mappings themselves 626 627 628 //as an inner class it has access to the factory etc of the enclosing class 629 public class GeneMappingRowHandler implements DBResultHandler { 630 631 // the magic strings to be used as property keys for HashMap in Ibatis 632 private final String gene = "gene"; 633 private final String xref = "xref"; 634 private final String target = "target"; 635 private final String coords = "coords"; 636 private final String coordSystemID = "csID"; 637// private final String xdb = "xdb"; 638 639 private DADNASequence parentSeq = null; 640 private DAGene objectResult = null; 641 private List<DAGene> listResult = new ArrayList<DAGene>(); 642 private List<HashMap> rawResults = null; 643 644 public GeneMappingRowHandler(List<HashMap> results) { 645 rawResults = results; 646 } 647 648 public GeneMappingRowHandler(List<HashMap> results, DADNASequence parent) { 649 rawResults = results; 650 parentSeq = parent; 651 } 652 653 @Override 654 public List<DAGene> getListResult() { 655 return listResult; 656 } 657 658 @Override 659 public DAGene getObjectResult() { 660 return objectResult; 661 } 662 663 public void handleResult() throws DAOException { 664 665 if (rawResults == null || rawResults.isEmpty()) { 666 return; 667 } 668 669 for (HashMap map : rawResults) { 670 handleRow(map); 671 } 672 673 } 674 675 private void handleRow(HashMap result) throws DAOException { 676 677 if (result == null || result.isEmpty()) { 678 return; 679 } 680 681 DAGene rowGene = null; 682 if (parentSeq != null) { 683 rowGene = this.parseResult(result, parentSeq); 684 } else { 685 rowGene = this.parseResult(result); 686 } 687 688 if (rowGene != null) { 689 this.objectResult = rowGene; 690 this.listResult.add(rowGene); 691 } 692 693 } 694 695 private DAGene parseResult(HashMap result, DADNASequence parent) throws DAOException { 696 697 if (result == null || parent == null) { 698 return null; 699 } 700 701 DADNASequence pparentSeq = parent; 702 703 DAGene pgene = null; 704 DADNASequence ptarget = null; 705 Coordinate pcoords = null; 706 DAXRef pxref = null; 707 Integer pcsID = null; 708// ExternalDB db = null; 709 710 pgene = (DAGene) result.get(this.gene); 711 pcoords = (Coordinate) result.get(this.coords); 712 ptarget = (DADNASequence) result.get(this.target); 713 pcsID = (Integer) result.get(this.coordSystemID); 714 pxref = (DAXRef) result.get(this.xref); 715// db = (ExternalDB) result.get(this.xdb); 716 717 //we only want genes on the parent sequence 718 //this should never fail if we have done the sql correctly 719 if (pgene == null || pcoords == null || ptarget == null || !ptarget.getId().equals(pparentSeq.getId())) { 720 return null; 721 } 722 723 if (pgene.getDaoFactory() == null) { 724 //pgene.setType(FeatureType.gene); 725 pgene.setDaoFactory(daoFactory); 726 } 727 728// if (db != null) { 729// int originalHashCode = db.originalHashCode(); 730// db = ((CoreDatabase) daoFactory.getDatabase()).validateExternalDB(db); 731// int checkedHashCode = db.originalHashCode(); 732// if (originalHashCode-checkedHashCode !=0) { 733// System.out.println("*** FAILED TO REUSE EXTERNALDB"); 734// } else { 735// System.out.println("*** successfully reused externaldb"); 736// } 737// } 738 739 if (pgene.getDisplayXRef() == null) { 740 if (pxref != null) { 741 pxref.setDaoFactory(daoFactory); 742// pxref.setDB(db); 743 pgene.setDisplayXRef(pxref); 744 } 745 } 746 747 //check if the gene object has somehow been returned from a cache and it 748 //has a mapping to a seq region with the same id as the parentSeq: if 749 //so, swap it for the parentSeq 750 for (Mapping m : pgene.getLoadedMappings()) { 751 if (m.getTarget().getId().equals(pparentSeq.getId())) { 752 if (pparentSeq.getDaoFactory() == null) { 753 pparentSeq.setDaoFactory(daoFactory); 754 } 755 if (pparentSeq.getCoordSystem() == null) { 756 if (singleSpecies) { 757 pparentSeq.setCoordSystem(ssFactory.getDatabase().getCSByID(pcsID)); 758 } else { 759 pparentSeq.setCoordSystem(collFactory.getDatabase().getCSByID(species, pcsID)); 760 } 761 } 762 //do the switch 763 m.setTarget(pparentSeq); 764 m.setTargetCoordinates(pcoords); 765 Mapping.addReverseMapping(m); 766 return pgene; 767 } 768 } 769 770 771 Mapping mapping = new Mapping(); 772 mapping.setSource(pgene); 773 mapping.setTargetCoordinates(pcoords); 774 775 // at this point we could look to see if we have this sequence in cache 776 777 if (pparentSeq.getDaoFactory() == null) { 778 pparentSeq.setDaoFactory(daoFactory); 779 } 780 781 if (pparentSeq.getCoordSystem() == null) { 782 if (singleSpecies) { 783 pparentSeq.setCoordSystem(ssFactory.getDatabase().getCSByID(pcsID)); 784 } else { 785 pparentSeq.setCoordSystem(collFactory.getDatabase().getCSByID(species, pcsID)); 786 } 787 } 788 789 mapping.setTarget(pparentSeq); 790 if(pgene.addMapping(mapping)) { 791 Mapping.addReverseMapping(mapping); 792 } 793 return pgene; 794 795 796 } 797 798 private DAGene parseResult(HashMap result) throws DAOException { 799 800 if (result == null || result.isEmpty()) { 801 return null; 802 } 803 804 DAGene pgene = null; 805 DADNASequence ptarget = null; 806 Coordinate pcoords = null; 807 DAXRef pxref = null; 808 Integer pcsID = null; 809// ExternalDB db = null; 810 811 pgene = (DAGene) result.get(this.gene); 812 813 if (pgene == null) { 814 return null; 815 } 816 817 if (pgene.getDaoFactory() == null) { 818 // pgene.setType(FeatureType.gene); 819 pgene.setDaoFactory(daoFactory); 820 } 821 822// db = (ExternalDB) result.get(this.xdb); 823// if (db != null) { 824// int originalHashCode = db.originalHashCode(); 825// db = ((CoreDatabase) daoFactory.getDatabase()).validateExternalDB(db); 826// int checkedHashCode = db.originalHashCode(); 827// if (originalHashCode-checkedHashCode !=0) { 828// System.out.println("*** FAILED TO REUSE EXTERNALDB"); 829// } else { 830// System.out.println("*** successfully reused externaldb"); 831// } 832// } 833 834 835 if (pgene.getDisplayXRef() == null) { 836 pxref = (DAXRef) result.get(this.xref); 837 if (pxref != null) { 838 pxref.setDaoFactory(daoFactory); 839// pxref.setDB(db); 840 pgene.setDisplayXRef(pxref); 841 } 842 } 843 844 pcoords = (Coordinate) result.get(this.coords); 845 846 //later we will check to see if we already have this in cache 847 //(at moment just for chromosomes) 848 ptarget = (DADNASequence) result.get(this.target); 849 850 pcsID = (Integer) result.get(this.coordSystemID); 851 852 if (pcoords == null || ptarget == null) { 853 return pgene; 854 } 855 856 Mapping mapping = new Mapping(); 857 mapping.setSource(pgene); 858 mapping.setTargetCoordinates(pcoords); 859 860 //we want to convert the DADNASequence to the correct type if it is an assembly! 861 862 CoordinateSystem targetCS = null; 863 864 if (singleSpecies) { 865 targetCS = ssFactory.getDatabase().getCSByID(pcsID); 866 } else { 867 targetCS =collFactory.getDatabase().getCSByID(species, pcsID); 868 } 869 870 if (targetCS.isSequenceLevel()) { 871 ptarget.setCoordSystem(targetCS); 872 } else if (EnsemblCoordSystemType.chromosome.equals(targetCS.getType())) { 873 ptarget = new DAChromosome((DAOCoreFactory) daoFactory); 874 ptarget.setId(((DADNASequence) result.get(this.target)).getId()); 875 ptarget.setSpecies(species); 876 ptarget.setCoordSystem(targetCS); 877 878 //look to see if we have this sequence in cache 879 ptarget = species.getCachedChromosome((DAChromosome) ptarget); 880 881 } else { 882 ptarget = new DAAssembledDNASequence((DAOCoreFactory) daoFactory); 883 884 ptarget.setId(((DADNASequence) result.get(this.target)).getId()); 885 ptarget.setCoordSystem(targetCS); 886 887 //look to see if we have this sequence in cache 888 ptarget = species.getCachedFragment((DAAssembledDNASequence) ptarget); 889 } 890 891 892 893 mapping.setTarget(ptarget); 894 if (pgene.addMapping(mapping)) { 895 Mapping.addReverseMapping(mapping); 896 } 897 return pgene; 898 899 } 900 } 901 902 //as an inner class it has access to the factory etc of the enclosing class 903 public class MappingRowHandler implements DBResultHandler { 904 905 // the magic strings to be used as property keys for HashMap in Ibatis 906 private final String gene = "gene"; 907 private final String xref = "xref"; 908 private final String target = "target"; 909 private final String coords = "coords"; 910 private final String coordSystemID = "csID"; 911// private final String xdb = "xdb"; 912 913 private DADNASequence parentSeq = null; 914 private Mapping objectResult = null; 915 private List<Mapping> listResult = new ArrayList<Mapping>(); 916 private List<HashMap> rawResults = null; 917 918 public MappingRowHandler(List<HashMap> results) { 919 rawResults = results; 920 } 921 922 public MappingRowHandler(List<HashMap> results, DADNASequence parent) { 923 rawResults = results; 924 parentSeq = parent; 925 } 926 927 @Override 928 public List<Mapping> getListResult() { 929 return listResult; 930 } 931 932 @Override 933 public Mapping getObjectResult() { 934 return objectResult; 935 } 936 937 938 public void handleResult() throws DAOException { 939 940 if (rawResults == null || rawResults.isEmpty()) { 941 return; 942 } 943 944 for (HashMap map : rawResults) { 945 handleRow(map); 946 } 947 948 } 949 950 private void handleRow(HashMap result) throws DAOException { 951 952 if (result == null || result.isEmpty()) { 953 return; 954 } 955 956 Mapping rowMapping = null; 957 if (parentSeq != null) { 958 rowMapping = this.parseMappingResult(result, parentSeq); 959 } else { 960 rowMapping = this.parseMappingResult(result); 961 } 962 963 if (rowMapping != null) { 964 this.objectResult = rowMapping; 965 this.listResult.add(rowMapping); 966 } 967 968 } 969 970 971 972 private Mapping parseMappingResult(HashMap result, DADNASequence parent) throws DAOException { 973 974 if (result == null || parent == null) { 975 return null; 976 } 977 978 DADNASequence pparentSeq = parent; 979 980 DAGene pgene = null; 981 DADNASequence ptarget = null; 982 Coordinate pcoords = null; 983 DAXRef pxref = null; 984 Integer pcsID = null; 985// ExternalDB db = null; 986 987 pgene = (DAGene) result.get(this.gene); 988 pcoords = (Coordinate) result.get(this.coords); 989 ptarget = (DADNASequence) result.get(this.target); 990 pcsID = (Integer) result.get(this.coordSystemID); 991 pxref = (DAXRef) result.get(this.xref); 992// db = (ExternalDB) result.get(this.xdb); 993 994 //we only want genes on the parent sequence 995 //this should never fail if we have done the sql correctly 996 if (pgene == null || pcoords == null || ptarget == null || !ptarget.getId().equals(pparentSeq.getId())) { 997 return null; 998 } 999 1000 if (pgene.getDaoFactory() == null) { 1001 //pgene.setType(FeatureType.gene); 1002 pgene.setDaoFactory(daoFactory); 1003 } 1004 1005// if (db != null) { 1006// int originalHashCode = db.originalHashCode(); 1007// db = ((CoreDatabase) daoFactory.getDatabase()).validateExternalDB(db); 1008// int checkedHashCode = db.originalHashCode(); 1009// if (originalHashCode-checkedHashCode !=0) { 1010// System.out.println("*** FAILED TO REUSE EXTERNALDB"); 1011// } else { 1012// System.out.println("*** successfully reused externaldb"); 1013// } 1014// } 1015 1016 1017 if (pgene.getDisplayXRef() == null) { 1018 pxref = (DAXRef) result.get(this.xref); 1019 if (pxref != null) { 1020 pxref.setDaoFactory(daoFactory); 1021// pxref.setDB(db); 1022 pgene.setDisplayXRef(pxref); 1023 } 1024 } 1025 1026 //check if the gene object has somehow been returned from a cache and it 1027 //has a mapping to a seq region with the same id as the parentSeq: if 1028 //so, swap it for the parentSeq 1029 for (Mapping m : pgene.getLoadedMappings()) { 1030 if (m.getTarget().getId().equals(pparentSeq.getId())) { 1031 if (pparentSeq.getDaoFactory() == null) { 1032 pparentSeq.setDaoFactory(daoFactory); 1033 } 1034 if (pparentSeq.getCoordSystem() == null) { 1035 if (singleSpecies) { 1036 pparentSeq.setCoordSystem(ssFactory.getDatabase().getCSByID(pcsID)); 1037 } else { 1038 pparentSeq.setCoordSystem(collFactory.getDatabase().getCSByID(species, pcsID)); 1039 } 1040 } 1041 1042 //do the switch 1043 m.setTarget(pparentSeq); 1044 m.setTargetCoordinates(pcoords); 1045 Mapping.addReverseMapping(m); 1046 return m; 1047 } 1048 } 1049 1050 1051 Mapping mapping = new Mapping(); 1052 mapping.setSource(pgene); 1053 mapping.setTargetCoordinates(pcoords); 1054 1055 // at this point we could look to see if we have this sequence in cache 1056 1057 if (pparentSeq.getDaoFactory() == null) { 1058 pparentSeq.setDaoFactory(daoFactory); 1059 } 1060 1061 if (pparentSeq.getCoordSystem() == null) { 1062 if (singleSpecies) { 1063 pparentSeq.setCoordSystem(ssFactory.getDatabase().getCSByID(pcsID)); 1064 } else { 1065 pparentSeq.setCoordSystem(collFactory.getDatabase().getCSByID(species, pcsID)); 1066 } 1067 } 1068 1069 mapping.setTarget(pparentSeq); 1070 if (pgene.addMapping(mapping)) { 1071 Mapping.addReverseMapping(mapping); 1072 } 1073 return mapping; 1074 1075 1076 } 1077 1078 private Mapping parseMappingResult(HashMap result) throws DAOException { 1079 1080 if (result == null || result.isEmpty()) { 1081 return null; 1082 } 1083 1084 DAGene pgene = null; 1085 DADNASequence ptarget = null; 1086 Coordinate pcoords = null; 1087 DAXRef pxref = null; 1088 Integer pcsID = null; 1089// ExternalDB db = null; 1090 1091 pgene = (DAGene) result.get(this.gene); 1092// db = (ExternalDB) result.get(this.xdb); 1093 1094 if (pgene == null) { 1095 return null; 1096 } 1097 1098 if (pgene.getDaoFactory() == null) { 1099 //pgene.setType(FeatureType.gene); 1100 pgene.setDaoFactory(daoFactory); 1101 } 1102 1103// if (db != null) { 1104// int originalHashCode = db.originalHashCode(); 1105// db = ((CoreDatabase) daoFactory.getDatabase()).validateExternalDB(db); 1106// int checkedHashCode = db.originalHashCode(); 1107// if (originalHashCode-checkedHashCode !=0) { 1108// System.out.println("*** FAILED TO REUSE EXTERNALDB"); 1109// } else { 1110// System.out.println("*** successfully reused externaldb"); 1111// } 1112// } 1113 1114 if (pgene.getDisplayXRef() == null) { 1115 pxref = (DAXRef) result.get(this.xref); 1116 1117 if (pxref != null) { 1118// pxref.setDB(db); 1119 pxref.setDaoFactory(daoFactory); 1120 pgene.setDisplayXRef(pxref); 1121 } 1122 } 1123 1124 pcoords = (Coordinate) result.get(this.coords); 1125 ptarget = (DADNASequence) result.get(this.target); 1126 pcsID = (Integer) result.get(this.coordSystemID); 1127 1128// if (pcoords == null || ptarget == null) { 1129// return pgene; 1130// } 1131 1132 //check to see we are not adding a duplicate mapping 1133 //to a rowGene retreived from cache, if we already have a mapping for 1134 //this id - don't add it again 1135 1136// for (Mapping m : pgene.getLoadedMappings()) { 1137// if (m.getTarget().getId().equals(ptarget.getId())) { 1138// Mapping.addReverseMapping(m); 1139// return m; 1140// } 1141// } 1142 1143 Mapping mapping = new Mapping(); 1144 mapping.setSource(pgene); 1145 mapping.setTargetCoordinates(pcoords); 1146 1147 // at this point we could look to see if we have this sequence in cache 1148 1149 1150 //we want to convert the DADNASequence to the correct type if it is an assembly! 1151 1152 CoordinateSystem targetCS = null; 1153 1154 if (singleSpecies) { 1155 targetCS = ssFactory.getDatabase().getCSByID(pcsID); 1156 } else { 1157 targetCS =collFactory.getDatabase().getCSByID(species, pcsID); 1158 } 1159 1160 if (targetCS.isSequenceLevel()) { 1161 ptarget.setCoordSystem(targetCS); 1162 } else if (targetCS.getType().equals(EnsemblCoordSystemType.chromosome)) { 1163 ptarget = new DAChromosome(); 1164 ptarget.setId(((DADNASequence) result.get(this.target)).getId()); 1165 ptarget.setCoordSystem(targetCS); 1166 } else { 1167 ptarget = new DAAssembledDNASequence(); 1168 ptarget.setId(((DADNASequence) result.get(this.target)).getId()); 1169 ptarget.setCoordSystem(targetCS); 1170 } 1171 1172 ptarget.setDaoFactory(daoFactory); 1173 1174 mapping.setTarget(ptarget); 1175 if (pgene.addMapping(mapping)) { 1176 Mapping.addReverseMapping(mapping); 1177 } 1178 return mapping; 1179 1180 } 1181 1182 1183 } 1184 1185 1186}