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.exception.DAOException;
024    import java.util.ArrayList;
025    import java.util.HashMap;
026    import java.util.List;
027    import org.apache.ibatis.session.SqlSession;
028    import uk.ac.roslin.ensembl.dao.coreaccess.GeneDAO;
029    import uk.ac.roslin.ensembl.datasourceaware.core.DAGene;
030    import uk.ac.roslin.ensembl.config.FeatureType;
031    import uk.ac.roslin.ensembl.model.Mapping;
032    import uk.ac.roslin.ensembl.datasourceaware.DAXRef;
033    import uk.ac.roslin.ensembl.datasourceaware.core.DAAssembledDNASequence;
034    import uk.ac.roslin.ensembl.datasourceaware.core.DAChromosome;
035    import uk.ac.roslin.ensembl.datasourceaware.core.DADNASequence;
036    import uk.ac.roslin.ensembl.dao.database.DBCollectionSpecies;
037    import uk.ac.roslin.ensembl.mapper.handler.DBResultHandler;
038    import uk.ac.roslin.ensembl.mapper.query.FeatureQuery;
039    import uk.ac.roslin.ensembl.mapper.core.GeneMapper;
040    import uk.ac.roslin.ensembl.model.Coordinate;
041    import uk.ac.roslin.ensembl.model.core.CoreObject;
042    import uk.ac.roslin.ensembl.model.core.DNASequence;
043    import uk.ac.roslin.ensembl.config.EnsemblCoordSystemType;
044    import uk.ac.roslin.ensembl.dao.factory.DAOCollectionCoreFactory;
045    import uk.ac.roslin.ensembl.dao.factory.DAOCoreFactory;
046    import uk.ac.roslin.ensembl.dao.factory.DAOSingleSpeciesCoreFactory;
047    import uk.ac.roslin.ensembl.model.core.CoordinateSystem;
048    
049    public class DBGeneDAO extends DBCoreObjectDAO implements GeneDAO {
050    
051        //if the meta table tells us that genebuild.level is 'toplevel'
052        //we can grab the top ranked CS and use this for all genes
053        //there may be other values than 'toplevel' - i dont know what :)
054        //if the build level isn't annotated we have to get the possible CS levels
055        //from meta_coord and use which ever one is approriate!
056        CoordinateSystem geneBuildCS = null;
057    
058    
059        public DBGeneDAO() {
060            super();
061        }
062    
063        public DBGeneDAO(DAOSingleSpeciesCoreFactory factory) throws DAOException {
064            super(factory);
065    
066            //we want to initialize the GeneDAO so that it knows which COordinate system
067            //it needs to quwery about genes
068    
069            geneBuildCS = this.ssFactory.getDatabase().getBuildCoordSystem(FeatureType.gene.toString());
070            //what if this is null or throws an exception?
071            //if it throws an exception we are probably in some sort of bad factory environment
072            if (geneBuildCS==null) {
073                geneBuildCS=this.ssFactory.getDatabase().getTopLevelCoordSystem();
074            }
075        }
076    
077        public DBGeneDAO(DAOCollectionCoreFactory factory) throws DAOException {
078            super(factory);
079            geneBuildCS= this.collFactory.getDatabase().getBuildCoordSystem(species, FeatureType.gene.toString());
080            //what if this is null  or throw an exception?
081            //if it throws an exception we are probably in some sorto f baf dfactory environment
082            if (geneBuildCS==null) {
083                geneBuildCS=this.collFactory.getDatabase().getTopLevelCS(species);
084            }
085        }
086    
087        /**
088         * Uses the stableid of an object to fill in missing data that would have been
089         * present if the the gene had intially been made by a call to getGeneByStableID
090         * or getGeneByID.
091         * @param object
092         * @throws DAOException
093         */
094        @Override
095        public void reInitialize(CoreObject object) throws DAOException {
096    
097            if (object == null ||  !( object instanceof DAGene) ) {
098                throw new DAOException("Object not a DAGene");
099            }
100    
101            DAGene gene = (DAGene) object;
102    
103            //the DAO method requires a stableID
104            if (gene.getStableID()==null || gene.getStableID().isEmpty() ) {
105                return;
106            }
107    
108            DAGene temp = this.getGeneByStableID(gene.getStableID());
109    
110            gene.setDisplayXRef(temp.getDisplayXRef());
111            gene.setBiotype(temp.getBiotype());
112            gene.setId(temp.getId());
113            gene.setCanonicalTranscriptID(temp.getCanonicalTranscriptID());
114            gene.setCreationDate(temp.getCreationDate());
115            gene.setModificationDate(temp.getModificationDate());
116            gene.setDescription(temp.getDescription());
117    
118            for (Mapping tempMapping :temp.getMappings()) {
119    
120                Mapping tempRevMapping = tempMapping.getReverseMapping();
121                if (tempRevMapping != null) {
122                    tempRevMapping.setTarget(gene);
123                }
124                tempMapping.setSource(gene);
125                gene.addMapping(tempMapping);
126    
127    //            Mapping mapping = new Mapping();
128    //            mapping.setSource(gene);
129    //            mapping.setTargetCoordinates(tempMapping.getTargetCoordinates());
130    ////            m.getTarget().clearAllMappings();
131    //            mapping.setTarget(tempMapping.getTarget());
132    //            if (gene.addMapping(mapping)) {
133    //                Mapping.addReverseMapping(mapping);
134    //            }
135            }
136    
137        }
138    
139        /**
140         * @param id
141         * @return
142         * @throws DAOException
143         */
144        @Override
145        public DAGene getGeneByID(Integer id) throws DAOException {
146            
147            if (id==null) {
148                return null;
149            }
150    
151            FeatureQuery q = new FeatureQuery();
152            q.setFeatureID(id);
153            if (!singleSpecies) {
154                try {
155                    q.setSpeciesID(species.getDBSpeciesID(this.getFactory().getDBVersion()));
156                } catch (Exception e) {
157                    throw new DAOException("No species ID context for this query!", e);
158                }
159            }
160            return this.getGene(q);
161        }
162    
163        @Override
164        public DAGene addGeneByIDOnParent(Integer id, DNASequence parent) throws DAOException {
165            if (parent == null || !(parent instanceof DADNASequence) || ((CoreObject) parent).getId() == null) {
166                throw new DAOException("No valid parent DNA provided");
167            }
168            if (id == null ) {
169                return null;
170            }
171            FeatureQuery q = new FeatureQuery();
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            q.setFeatureID(id);
180            //this is redundant - if the rowGene doesnt map on this sequence
181            //adding this parameter or not we would still get no genes back
182            //adding this parameter has the effect of
183            //making this a different query to getGeneByID and therefore
184            //will return a differnt object  - not a cached one
185            q.setParentSequenceID(parent.getId());
186            return this.getGeneOnParent(q, (DADNASequence) parent);
187        }
188    
189        /**
190         * @param stableID
191         * @return
192         * @throws DAOException
193         */
194        @Override
195        public DAGene getGeneByStableID(String stableID) throws DAOException {
196            if (stableID==null || stableID.isEmpty()  ) {
197                return null;
198            }
199    
200            FeatureQuery q = new FeatureQuery();
201            if (!singleSpecies) {
202                try {
203                    q.setSpeciesID(species.getDBSpeciesID(this.getFactory().getDBVersion()));
204                } catch (Exception e) {
205                    throw new DAOException("No species ID context for this query!", e);
206                }
207            }
208            q.setFeatureStableID(stableID.trim());
209            return this.getGene(q);
210        }
211    
212        /**
213         * The gene returned has mapping to a sequence region - and the id for 
214         * the coordinate system that this region belongs to
215         * @param stableID
216         * @param parent
217         * @return
218         * @throws DAOException
219         */
220        @Override
221        public DAGene addGeneByStableIDOnParent(String stableID, DNASequence parent) throws DAOException {
222            if (parent == null || !(parent instanceof DADNASequence) || ((CoreObject) parent).getId() == null) {
223                throw new DAOException("No valid parent DNA provided");
224            }
225            if (stableID == null || stableID.isEmpty() ) {
226                return null;
227            }
228            FeatureQuery q = new FeatureQuery();
229            if (!singleSpecies) {
230                try {
231                    q.setSpeciesID(species.getDBSpeciesID(this.getFactory().getDBVersion()));
232                } catch (Exception e) {
233                    throw new DAOException("No species ID context for this query!", e);
234                }
235            }
236            q.setFeatureStableID(stableID.trim());
237            //this is redundant - if the rowGene doesnt map on this sequence
238            //adding this parameter or not we would still get no genes back
239            //adding this parameter has the effect of
240            //making this a different query to getGeneByID and therefore
241            //will return a differnt object  - not a cached one
242            q.setParentSequenceID(parent.getId());
243            return this.getGeneOnParent(q, (DADNASequence) parent);
244        }
245    
246        @Override
247        public List<Mapping> getGeneMappingsOnRegion(DNASequence region, Coordinate coords) throws DAOException  {
248    
249            List<Mapping> mappings = new ArrayList<Mapping>();
250            FeatureQuery q = new FeatureQuery();
251            if (!singleSpecies) {
252                try {
253                    q.setSpeciesID(species.getDBSpeciesID(this.getFactory().getDBVersion()));
254                } catch (Exception e) {
255                    throw new DAOException("No species ID context for this query!", e);
256                }
257            }
258            CoordinateSystem cs = null;
259    
260            if (region == null || region.getId()==null || region.getCoordSystem()== null ) {
261                throw new DAOException("No valid region or coordinate system specified");
262            } else {
263                cs = region.getCoordSystem();
264                q.setParentSequenceID(region.getId());
265                q.setCoordinateSystemID(cs.getId());
266            }
267    
268            if (coords != null) {
269                q.setParentStart(coords.getStart());
270                q.setParentStop(coords.getEnd());
271            }
272    
273    //        //what happens if we dont have a CS??
274    //        //do we want to try with the gene build CS is if there is one
275    //        //this is 'always' toplevel i.e. 1
276    //        //but the sequence might not be at this level
277    //        //so we would have to checke this before doing it
278    //        //probably safest to force a lazy load on sequence.getCoordSystem()
279    //        //i.e not do this....
280    //        else {
281    //            cs = this.geneBuildCS;
282    //            //q.setCoordinateSystemID(this.geneBuildCS.getId());
283    //        }
284    
285            //for maximum length
286            //will need different method if constructed from CollectionDB
287    
288            Integer max = null;
289            if (this.singleSpecies) {
290                    max= this.ssFactory.getDatabase().getMaxLengthForFeature(FeatureType.gene, this.geneBuildCS);
291            } else {
292                    max= this.collFactory.getDatabase().getMaxLengthForFeature((DBCollectionSpecies) species, FeatureType.gene, this.geneBuildCS);
293            }
294    
295            if (max != null) {
296                q.setMaximumFeatureLength(max);
297            }
298    
299            //out = this.getGenesOnParent(q, (DADNASequence) region);
300    
301            mappings = this.getMappingsOnParent(q, (DADNASequence) region);
302    
303    
304            // this gets the desired genes filtered by stand if specified
305            // probably should be done in the calling class
306    
307    //        if (coords.getStrand() == null) {
308    //            for (Mapping m : mappings) {
309    //                out.add((DAGene) m.getSource());
310    //            }
311    //        } else {
312    //            for (Mapping m : mappings) {
313    //                if (m.getTargetCoordinates().getStrand().equals(coords.getStrand())) {
314    //                    out.add((DAGene) m.getSource());
315    //                }
316    //            }
317    //        }
318    
319            return mappings;
320        }
321    
322       //*******************************
323    
324        private DAGene getGene(FeatureQuery query) throws DAOException {
325            DAGene out = null;
326            GeneMappingRowHandler handler = null;
327            List<HashMap> result;
328    
329            SqlSession session = null;
330    
331            try {
332                session = this.getFactory().getNewSqlSession();
333                GeneMapper mapper = session.getMapper(GeneMapper.class);
334                result = mapper.getGene(query);
335            } catch (Exception e) {
336                throw new DAOException("Failed to call getGene", e);
337            } finally {
338                if (session != null) {
339                    session.close();
340                }
341            }
342    
343            if (result != null && !result.isEmpty()) {
344    
345                handler = new GeneMappingRowHandler(result);
346                handler.handleResult();
347                out = handler.getObjectResult();
348            }
349    
350            return out;
351        }
352    
353        private DAGene getGeneOnParent(FeatureQuery query, DADNASequence parent) throws DAOException {
354            DAGene out = null;
355            GeneMappingRowHandler handler = null;
356            List<HashMap> result;
357    
358            SqlSession session = null;
359    
360            try {
361                session = this.getFactory().getNewSqlSession();
362                GeneMapper mapper = session.getMapper(GeneMapper.class);
363                result = mapper.getGene(query);
364            } catch (Exception e) {
365                throw new DAOException("Failed to call getGeneOnParent", e);
366            } finally {
367                if (session != null) {
368                    session.close();
369                }
370            }
371    
372            if (result != null && !result.isEmpty()) {
373    
374                handler = new GeneMappingRowHandler(result, parent);
375                handler.handleResult();
376                out = handler.getObjectResult();
377            }
378    
379            return out;
380        }
381    
382        private List<Mapping> getMappingsOnParent(FeatureQuery query, DADNASequence parent) throws DAOException {
383            List<Mapping> out = null;
384    
385            MappingRowHandler handler = null;
386            List<HashMap> result;
387    
388            SqlSession session = null;
389    
390            try {
391                session = this.getFactory().getNewSqlSession();
392                GeneMapper mapper = session.getMapper(GeneMapper.class);
393                result = mapper.getGene(query);
394            } catch (Exception e) {
395                throw new DAOException("Failed to call getMappingsOnParent", e);
396            } finally {
397                if (session != null) {
398                    session.close();
399                }
400            }
401    
402            if (result != null && !result.isEmpty()) {
403    
404                handler = new MappingRowHandler(result, parent);
405                handler.handleResult();
406                out = handler.getListResult();
407            }
408    
409            return out;
410        }
411    
412        //*********************************
413    
414        // I haven't decided whether it is better to get theobjects
415        //(with the mappings filled in)
416        // or to get the mappings themselves
417    
418    
419        //as an inner class it has access to the factory etc of the enclosing class
420        public class GeneMappingRowHandler implements DBResultHandler {
421    
422            // the magic strings to be used as property keys for HashMap in Ibatis
423            private final String gene = "gene";
424            private final String xref = "xref";
425            private final String target = "target";
426            private final String coords = "coords";
427            private final String coordSystemID = "csID";
428            private DADNASequence parentSeq = null;
429            private DAGene objectResult = null;
430            private List<DAGene> listResult = new ArrayList<DAGene>();
431            private List<HashMap> rawResults = null;
432    
433            public GeneMappingRowHandler(List<HashMap> results) {
434                rawResults = results;
435            }
436    
437            public GeneMappingRowHandler(List<HashMap> results, DADNASequence parent) {
438                rawResults = results;
439                parentSeq = parent;
440            }
441    
442            @Override
443            public List<DAGene> getListResult() {
444                return listResult;
445            }
446    
447            @Override
448            public DAGene getObjectResult() {
449                return objectResult;
450            }
451    
452            public void handleResult() throws DAOException {
453    
454                if (rawResults == null || rawResults.isEmpty()) {
455                    return;
456                }
457    
458                for (HashMap map : rawResults) {
459                    handleRow(map);
460                }
461    
462            }
463    
464            private void handleRow(HashMap result) throws DAOException {
465    
466                if (result == null || result.isEmpty()) {
467                    return;
468                }
469    
470                DAGene rowGene = null;
471                if (parentSeq != null) {
472                    rowGene = this.parseResult(result, parentSeq);
473                } else {
474                    rowGene = this.parseResult(result);
475                }
476    
477                if (rowGene != null) {
478                    this.objectResult = rowGene;
479                    this.listResult.add(rowGene);
480                }
481    
482            }
483    
484            private DAGene parseResult(HashMap result, DADNASequence parent) throws DAOException {
485    
486                if (result == null || parent == null) {
487                    return null;
488                }
489    
490                DADNASequence pparentSeq = parent;
491    
492                DAGene pgene = null;
493                DADNASequence ptarget = null;
494                Coordinate pcoords = null;
495                DAXRef pxref = null;
496                Integer pcsID = null;
497    
498                pgene = (DAGene) result.get(this.gene);
499                pcoords = (Coordinate) result.get(this.coords);
500                ptarget = (DADNASequence) result.get(this.target);
501                pcsID = (Integer) result.get(this.coordSystemID);
502                pxref = (DAXRef) result.get(this.xref);
503    
504                //we only want genes on the parent sequence
505                //this should never fail if we have done the sql correctly
506                if (pgene == null || pcoords == null || ptarget == null || !ptarget.getId().equals(pparentSeq.getId())) {
507                    return null;
508                }
509    
510                if (pgene.getDaoFactory() == null) {
511                    //pgene.setType(FeatureType.gene);
512                    pgene.setDaoFactory(daoFactory);
513                }
514    
515                if (pgene.getDisplayXRef() == null) {
516                    pxref = (DAXRef) result.get(this.xref);
517                    if (pxref != null) {
518                        pxref.setDaoFactory(daoFactory);
519                        pgene.setDisplayXRef(pxref);
520                    }
521                }
522    
523                //check if the gene object has somehow been returned from a cache and it
524                //has a mapping to a seq region with the same id as the parentSeq: if
525                //so, swap it for the parentSeq
526                for (Mapping m : pgene.getMappings()) {
527                    if (m.getTarget().getId().equals(pparentSeq.getId())) {
528                        if (pparentSeq.getDaoFactory() == null) {
529                            pparentSeq.setDaoFactory(daoFactory);
530                        }
531                        if (pparentSeq.getCoordSystem() == null) {
532                            if (singleSpecies) {
533                                pparentSeq.setCoordSystem(ssFactory.getDatabase().getCSByID(pcsID));
534                            } else {
535                                pparentSeq.setCoordSystem(collFactory.getDatabase().getCSByID(species, pcsID));
536                            }
537                        }
538                        //do the switch
539                        m.setTarget(pparentSeq);
540                        m.setTargetCoordinates(pcoords);
541                        Mapping.addReverseMapping(m);
542                        return pgene;
543                    }
544                }
545    
546    
547                Mapping mapping = new Mapping();
548                mapping.setSource(pgene);
549                mapping.setTargetCoordinates(pcoords);
550    
551                // at this point we could look to see if we have this sequence in cache
552    
553                if (pparentSeq.getDaoFactory() == null) {
554                    pparentSeq.setDaoFactory(daoFactory);
555                }
556    
557                if (pparentSeq.getCoordSystem() == null) {
558                     if (singleSpecies) {
559                            pparentSeq.setCoordSystem(ssFactory.getDatabase().getCSByID(pcsID));
560                     } else {
561                            pparentSeq.setCoordSystem(collFactory.getDatabase().getCSByID(species, pcsID));
562                     }
563                }
564    
565                mapping.setTarget(pparentSeq);
566                if(pgene.addMapping(mapping)) {
567                    Mapping.addReverseMapping(mapping);
568                }
569                return pgene;
570    
571    
572            }
573    
574            private DAGene parseResult(HashMap result) throws DAOException {
575    
576                if (result == null || result.isEmpty()) {
577                    return null;
578                }
579    
580                DAGene pgene = null;
581                DADNASequence ptarget = null;
582                Coordinate pcoords = null;
583                DAXRef pxref = null;
584                Integer pcsID = null;
585    
586                pgene = (DAGene) result.get(this.gene);
587    
588                if (pgene == null) {
589                    return null;
590                }
591    
592                if (pgene.getDaoFactory() == null) {
593                   // pgene.setType(FeatureType.gene);
594                    pgene.setDaoFactory(daoFactory);
595                }
596    
597                if (pgene.getDisplayXRef() == null) {
598                    pxref = (DAXRef) result.get(this.xref);
599                    if (pxref != null) {
600                        pxref.setDaoFactory(daoFactory);
601                        pgene.setDisplayXRef(pxref);
602                    }
603                }
604    
605                pcoords = (Coordinate) result.get(this.coords);
606    
607                //later we will check to see if we already have this in cache
608                //(at moment just for chromosomes)
609                ptarget = (DADNASequence) result.get(this.target);
610    
611                pcsID = (Integer) result.get(this.coordSystemID);
612    
613                if (pcoords == null || ptarget == null) {
614                    return pgene;
615                }
616    
617                Mapping mapping = new Mapping();
618                mapping.setSource(pgene);
619                mapping.setTargetCoordinates(pcoords);
620    
621                //we want to convert the DADNASequence to the correct type if it is an assembly!
622    
623                CoordinateSystem targetCS  = null;
624    
625                if (singleSpecies) {
626                        targetCS = ssFactory.getDatabase().getCSByID(pcsID);
627                   } else {
628                        targetCS =collFactory.getDatabase().getCSByID(species, pcsID);
629                   }
630    
631                if (targetCS.isSequenceLevel()) {
632                    ptarget.setCoordSystem(targetCS);
633                } else if (targetCS.getType().equals(EnsemblCoordSystemType.chromosome)) {
634                    ptarget = new DAChromosome((DAOCoreFactory) daoFactory);
635                    ptarget.setId(((DADNASequence) result.get(this.target)).getId());
636                    ptarget.setSpecies(species);
637                    ptarget.setCoordSystem(targetCS);
638                    
639                    //loook to see if we have this sequence in cache
640                    ptarget = species.getCachedChromosome((DAChromosome) ptarget);
641    
642                } else {
643                    ptarget = new DAAssembledDNASequence((DAOCoreFactory) daoFactory);
644                    ptarget.setId(((DADNASequence) result.get(this.target)).getId());
645                    ptarget.setCoordSystem(targetCS);
646    
647                    //not got a cache of assembled sequences yet to check
648                }
649    
650                
651    
652                mapping.setTarget(ptarget);
653                if (pgene.addMapping(mapping)) {
654                    Mapping.addReverseMapping(mapping);
655                }
656                return pgene;
657    
658            }
659        }
660    
661        //as an inner class it has access to the factory etc of the enclosing class
662        public class MappingRowHandler implements DBResultHandler {
663    
664            // the magic strings to be used as property keys for HashMap in Ibatis
665            private final String gene = "gene";
666            private final String xref = "xref";
667            private final String target = "target";
668            private final String coords = "coords";
669            private final String coordSystemID = "csID";
670            private DADNASequence parentSeq = null;
671            private Mapping objectResult = null;
672            private List<Mapping> listResult = new ArrayList<Mapping>();
673            private List<HashMap> rawResults = null;
674    
675            public MappingRowHandler(List<HashMap> results) {
676                rawResults = results;
677            }
678    
679            public MappingRowHandler(List<HashMap> results, DADNASequence parent) {
680                rawResults = results;
681                parentSeq = parent;
682            }
683    
684            @Override
685            public List<Mapping> getListResult() {
686                return listResult;
687            }
688    
689            @Override
690            public Mapping getObjectResult() {
691                return objectResult;
692            }
693    
694    
695            public void handleResult() throws DAOException {
696    
697                if (rawResults == null || rawResults.isEmpty()) {
698                    return;
699                }
700    
701                for (HashMap map : rawResults) {
702                    handleRow(map);
703                }
704    
705            }
706    
707            private void handleRow(HashMap result) throws DAOException {
708    
709                if (result == null || result.isEmpty()) {
710                    return;
711                }
712    
713                Mapping rowMapping = null;
714                if (parentSeq != null) {
715                    rowMapping = this.parseMappingResult(result, parentSeq);
716                } else {
717                    rowMapping = this.parseMappingResult(result);
718                }
719    
720                if (rowMapping != null) {
721                    this.objectResult = rowMapping;
722                    this.listResult.add(rowMapping);
723                }
724    
725            }
726    
727    
728    
729            private Mapping parseMappingResult(HashMap result, DADNASequence parent) throws DAOException {
730    
731                if (result == null || parent == null) {
732                    return null;
733                }
734    
735                DADNASequence pparentSeq = parent;
736    
737                DAGene pgene = null;
738                DADNASequence ptarget = null;
739                Coordinate pcoords = null;
740                DAXRef pxref = null;
741                Integer pcsID = null;
742    
743                pgene = (DAGene) result.get(this.gene);
744                pcoords = (Coordinate) result.get(this.coords);
745                ptarget = (DADNASequence) result.get(this.target);
746                pcsID = (Integer) result.get(this.coordSystemID);
747                pxref = (DAXRef) result.get(this.xref);
748    
749                //we only want genes on the parent sequence
750                //this should never fail if we have done the sql correctly
751                if (pgene == null || pcoords == null || ptarget == null || !ptarget.getId().equals(pparentSeq.getId())) {
752                    return null;
753                }
754    
755                if (pgene.getDaoFactory() == null) {
756                    //pgene.setType(FeatureType.gene);
757                    pgene.setDaoFactory(daoFactory);
758                }
759    
760                if (pgene.getDisplayXRef() == null) {
761                    pxref = (DAXRef) result.get(this.xref);
762                    if (pxref != null) {
763                        pxref.setDaoFactory(daoFactory);
764                        pgene.setDisplayXRef(pxref);
765                    }
766                }
767    
768                //check if the gene object has somehow been returned from a cache and it
769                //has a mapping to a seq region with the same id as the parentSeq: if
770                //so, swap it for the parentSeq
771                for (Mapping m : pgene.getMappings()) {
772                    if (m.getTarget().getId().equals(pparentSeq.getId())) {
773                        if (pparentSeq.getDaoFactory() == null) {
774                            pparentSeq.setDaoFactory(daoFactory);
775                        }
776                        if (pparentSeq.getCoordSystem() == null) {
777                            if (singleSpecies) {
778                                pparentSeq.setCoordSystem(ssFactory.getDatabase().getCSByID(pcsID));
779                            } else {
780                                pparentSeq.setCoordSystem(collFactory.getDatabase().getCSByID(species, pcsID));
781                            }
782                        }
783    
784                        //do the switch
785                        m.setTarget(pparentSeq);
786                        m.setTargetCoordinates(pcoords);
787                        Mapping.addReverseMapping(m);
788                        return m;
789                    }
790                }
791    
792    
793                Mapping mapping = new Mapping();
794                mapping.setSource(pgene);
795                mapping.setTargetCoordinates(pcoords);
796    
797                // at this point we could look to see if we have this sequence in cache
798    
799                if (pparentSeq.getDaoFactory() == null) {
800                    pparentSeq.setDaoFactory(daoFactory);
801                }
802    
803                if (pparentSeq.getCoordSystem() == null) {
804                if (singleSpecies) {
805                        pparentSeq.setCoordSystem(ssFactory.getDatabase().getCSByID(pcsID));
806                   } else {
807                        pparentSeq.setCoordSystem(collFactory.getDatabase().getCSByID(species, pcsID));
808                   }
809                }
810    
811                mapping.setTarget(pparentSeq);
812                if (pgene.addMapping(mapping)) {
813                    Mapping.addReverseMapping(mapping);
814                }
815                return mapping;
816    
817    
818            }
819    
820            private Mapping parseMappingResult(HashMap result) throws DAOException {
821    
822                if (result == null || result.isEmpty()) {
823                    return null;
824                }
825    
826                DAGene pgene = null;
827                DADNASequence ptarget = null;
828                Coordinate pcoords = null;
829                DAXRef pxref = null;
830                Integer pcsID = null;
831    
832                pgene = (DAGene) result.get(this.gene);
833    
834                if (pgene == null) {
835                    return null;
836                }
837    
838                if (pgene.getDaoFactory() == null) {
839                    //pgene.setType(FeatureType.gene);
840                    pgene.setDaoFactory(daoFactory);
841                }
842    
843                if (pgene.getDisplayXRef() == null) {
844                    pxref = (DAXRef) result.get(this.xref);
845                    if (pxref != null) {
846                        pxref.setDaoFactory(daoFactory);
847                        pgene.setDisplayXRef(pxref);
848                    }
849                }
850    
851                pcoords = (Coordinate) result.get(this.coords);
852                ptarget = (DADNASequence) result.get(this.target);
853                pcsID = (Integer) result.get(this.coordSystemID);
854    
855    //            if (pcoords == null || ptarget == null) {
856    //                return pgene;
857    //            }
858    
859                //check to see we are not adding a duplicate mapping
860                //to a rowGene retreived from cache, if we already have a mapping for
861                //this id - don't add it again
862    
863    //            for (Mapping m : pgene.getMappings()) {
864    //                if (m.getTarget().getId().equals(ptarget.getId())) {
865    //                    Mapping.addReverseMapping(m);
866    //                    return m;
867    //                }
868    //            }
869    
870                Mapping mapping = new Mapping();
871                mapping.setSource(pgene);
872                mapping.setTargetCoordinates(pcoords);
873    
874                // at this point we could look to see if we have this sequence in cache
875    
876    
877                //we want to convert the DADNASequence to the correct type if it is an assembly!
878    
879                CoordinateSystem targetCS  = null;
880    
881                if (singleSpecies) {
882                        targetCS = ssFactory.getDatabase().getCSByID(pcsID);
883                   } else {
884                        targetCS =collFactory.getDatabase().getCSByID(species, pcsID);
885                   }
886    
887                if (targetCS.isSequenceLevel()) {
888                    ptarget.setCoordSystem(targetCS);
889                } else if (targetCS.getType().equals(EnsemblCoordSystemType.chromosome)) {
890                    ptarget = new DAChromosome();
891                    ptarget.setId(((DADNASequence) result.get(this.target)).getId());
892                    ptarget.setCoordSystem(targetCS);
893                } else {
894                    ptarget = new DAAssembledDNASequence();
895                    ptarget.setId(((DADNASequence) result.get(this.target)).getId());
896                    ptarget.setCoordSystem(targetCS);
897                }
898    
899                ptarget.setDaoFactory(daoFactory);
900    
901                mapping.setTarget(ptarget);
902                if (pgene.addMapping(mapping)) {
903                    Mapping.addReverseMapping(mapping);
904                }
905                return mapping;
906    
907            }
908    
909    
910        }
911    
912    
913    }