ubic.gemma.persistence.service.genome.biosequence.BioSequenceDaoImpl.java Source code

Java tutorial

Introduction

Here is the source code for ubic.gemma.persistence.service.genome.biosequence.BioSequenceDaoImpl.java

Source

/*
 * The Gemma project.
 *
 * Copyright (c) 2006 University of British Columbia
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package ubic.gemma.persistence.service.genome.biosequence;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.FlushMode;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import ubic.gemma.model.common.description.DatabaseEntry;
import ubic.gemma.model.genome.Gene;
import ubic.gemma.model.genome.biosequence.BioSequence;
import ubic.gemma.model.genome.sequenceAnalysis.BioSequenceValueObject;
import ubic.gemma.persistence.service.AbstractDao;
import ubic.gemma.persistence.service.AbstractVoEnabledDao;
import ubic.gemma.persistence.util.BusinessKey;
import ubic.gemma.persistence.util.EntityUtils;

import java.util.*;

/**
 * @author pavlidis
 * @see    ubic.gemma.model.genome.biosequence.BioSequence
 */
@Repository
public class BioSequenceDaoImpl extends AbstractVoEnabledDao<BioSequence, BioSequenceValueObject>
        implements BioSequenceDao {

    @Autowired
    public BioSequenceDaoImpl(SessionFactory sessionFactory) {
        super(BioSequence.class, sessionFactory);
    }

    @Override
    public BioSequence findByAccession(DatabaseEntry databaseEntry) {
        BusinessKey.checkValidKey(databaseEntry);

        String queryString;
        List<BioSequence> results;
        if (databaseEntry.getId() != null) {
            queryString = "select b from BioSequence b inner join fetch b.sequenceDatabaseEntry d inner join fetch d.externalDatabase e  where d=:dbe";
            //noinspection unchecked
            results = this.getSessionFactory().getCurrentSession().createQuery(queryString)
                    .setParameter("dbe", databaseEntry).list();
        } else {
            queryString = "select b from BioSequence b inner join fetch b.sequenceDatabaseEntry d "
                    + "inner join fetch d.externalDatabase e where d.accession = :acc and e.name = :dbName";
            //noinspection unchecked
            results = this.getSessionFactory().getCurrentSession().createQuery(queryString)
                    .setParameter("acc", databaseEntry.getAccession())
                    .setParameter("dbName", databaseEntry.getExternalDatabase().getName()).list();
        }

        if (results.size() > 1) {
            this.debug(null, results);
            AbstractDao.log.warn("More than one instance of '" + BioSequence.class.getName()
                    + "' was found when executing query for accession=" + databaseEntry.getAccession());

            // favor the one with name matching the accession.
            for (Object object : results) {
                BioSequence bs = (BioSequence) object;
                if (bs.getName().equals(databaseEntry.getAccession())) {
                    return bs;
                }
            }

            AbstractDao.log.error("No biosequence really matches " + databaseEntry.getAccession());
            return null;

        } else if (results.size() == 1) {
            return results.iterator().next();
        } else {
            return null;
        }
    }

    @Override
    public Map<Gene, Collection<BioSequence>> findByGenes(Collection<Gene> genes) {
        if (genes == null || genes.isEmpty())
            return new HashMap<>();

        Map<Gene, Collection<BioSequence>> results = new HashMap<>();

        int batchSize = 500;

        if (genes.size() <= batchSize) {
            this.findByGenesBatch(genes, results);
            return results;
        }

        Collection<Gene> batch = new HashSet<>();

        for (Gene gene : genes) {
            batch.add(gene);
            if (batch.size() == batchSize) {
                this.findByGenesBatch(genes, results);
                batch.clear();
            }
        }

        if (!batch.isEmpty()) {
            this.findByGenesBatch(genes, results);
        }

        return results;
    }

    @Override
    public Collection<BioSequence> findByName(String name) {
        return this.findByProperty("name", name);
    }

    @Override
    public Collection<Gene> getGenesByAccession(String search) {
        //noinspection unchecked
        return this.getSessionFactory().getCurrentSession().createQuery(
                "select distinct gene from Gene as gene inner join gene.products gp,  BioSequence2GeneProduct as bs2gp"
                        + " inner join bs2gp.bioSequence bs "
                        + "inner join bs.sequenceDatabaseEntry de where gp=bs2gp.geneProduct "
                        + " and de.accession = :search ")
                .setParameter("search", search).list();
    }

    @Override
    public Collection<Gene> getGenesByName(String search) {
        try {
            //noinspection unchecked
            return this.getSessionFactory().getCurrentSession().createQuery(
                    "select distinct gene from Gene as gene inner join gene.products gp,  BioSequence2GeneProduct as bs2gp where gp=bs2gp.geneProduct "
                            + " and bs2gp.bioSequence.name like :search ")
                    .setString("search", search).list();

        } catch (org.hibernate.HibernateException ex) {
            throw super.convertHibernateAccessException(ex);
        }
    }

    @Override
    public Collection<BioSequence> thaw(final Collection<BioSequence> bioSequences) {
        if (bioSequences.isEmpty())
            return new HashSet<>();

        Collection<BioSequence> result = new HashSet<>();
        Collection<BioSequence> batch = new HashSet<>();

        for (BioSequence g : bioSequences) {
            batch.add(g);
            if (batch.size() == 100) {
                result.addAll(this.doThawBatch(batch));
                batch.clear();
            }
        }

        if (!batch.isEmpty()) {
            result.addAll(this.doThawBatch(batch));
        }

        return result;
    }

    @Override
    public BioSequence thaw(final BioSequence bioSequence) {
        if (bioSequence == null)
            return null;
        if (bioSequence.getId() == null)
            return bioSequence;

        List<?> res = this.getHibernateTemplate().findByNamedParam(
                "select b from BioSequence b "
                        + " left join fetch b.taxon tax left join fetch tax.externalDatabase "
                        + " left join fetch b.sequenceDatabaseEntry s left join fetch s.externalDatabase"
                        + " left join fetch b.bioSequence2GeneProduct bs2gp "
                        + " left join fetch bs2gp.geneProduct gp left join fetch gp.gene g"
                        + " left join fetch g.aliases left join fetch g.accessions  where b.id=:bid",
                "bid", bioSequence.getId());

        return (BioSequence) res.iterator().next();
    }

    @Override
    public BioSequence findByCompositeSequence(Long id) {
        return (BioSequence) this.getSessionFactory().getCurrentSession()
                .createQuery("select cs.biologicalCharacteristic from CompositeSequence as cs where cs.id = :id")
                .setParameter("id", id).uniqueResult();
    }

    @Override
    public BioSequenceValueObject loadValueObject(BioSequence entity) {
        return BioSequenceValueObject.fromEntity(entity);
    }

    @Override
    public Collection<BioSequenceValueObject> loadValueObjects(Collection<BioSequence> entities) {
        Collection<BioSequenceValueObject> vos = new LinkedHashSet<>();
        for (BioSequence e : entities) {
            vos.add(this.loadValueObject(e));
        }
        return vos;
    }

    @SuppressWarnings("unchecked")
    @Override
    public BioSequence find(BioSequence bioSequence) {

        BusinessKey.checkValidKey(bioSequence);

        Criteria queryObject = BusinessKey.createQueryObject(this.getSessionFactory().getCurrentSession(),
                bioSequence);
        queryObject.setReadOnly(true);
        queryObject.setFlushMode(FlushMode.MANUAL);
        /*
         * this initially matches on name and taxon only.
         */
        java.util.List<?> results = queryObject.list();
        Object result = null;
        if (results != null) {
            if (results.size() > 1) {
                this.debug(bioSequence, results);

                // Try to find the best match. See BusinessKey for more
                // explanation of why this is needed.
                BioSequence match = null;
                for (BioSequence res : (Collection<BioSequence>) results) {
                    if (res.equals(bioSequence)) {
                        if (match != null) {
                            AbstractDao.log.warn("More than one sequence in the database matches " + bioSequence
                                    + ", returning arbitrary match: " + match);
                            break;
                        }
                        match = res;
                    }
                }

                return match;

            } else if (results.size() == 1) {
                result = results.iterator().next();
            }
        }
        return (BioSequence) result;
    }

    @Override
    public BioSequence findOrCreate(BioSequence bioSequence) {
        BioSequence existingBioSequence = this.find(bioSequence);
        if (existingBioSequence != null) {
            return existingBioSequence;
        }
        if (AbstractDao.log.isDebugEnabled())
            AbstractDao.log.debug("Creating new: " + bioSequence);
        return this.create(bioSequence);
    }

    private Collection<? extends BioSequence> doThawBatch(Collection<BioSequence> batch) {
        //noinspection unchecked
        return this.getHibernateTemplate().findByNamedParam("select b from BioSequence b "
                + " left join fetch b.taxon tax left join fetch tax.externalDatabase left join fetch b.sequenceDatabaseEntry s "
                + " left join fetch s.externalDatabase" + " left join fetch b.bioSequence2GeneProduct bs2gp "
                + " left join fetch bs2gp.geneProduct gp left join fetch gp.gene g"
                + " left join fetch g.aliases left join fetch g.accessions  where b.id in (:bids)", "bids",
                EntityUtils.getIds(batch));
    }

    private void findByGenesBatch(Collection<Gene> genes, Map<Gene, Collection<BioSequence>> results) {
        //noinspection unchecked
        List<Object[]> qr = this.getSessionFactory().getCurrentSession()
                .createQuery("select distinct gene,bs from Gene gene inner join fetch gene.products ggp,"
                        + " BioSequence bs inner join bs.bioSequence2GeneProduct bs2gp inner join bs2gp.geneProduct bsgp"
                        + " where ggp=bsgp and gene in (:genes)")
                .setParameterList("genes", genes).list();
        for (Object[] oa : qr) {
            Gene g = (Gene) oa[0];
            BioSequence b = (BioSequence) oa[1];
            if (!results.containsKey(g)) {
                results.put(g, new HashSet<BioSequence>());
            }
            results.get(g).add(b);
        }
    }

    private void debug(BioSequence query, List<?> results) {
        StringBuilder sb = new StringBuilder();
        sb.append("\nMultiple BioSequences found matching query:\n");

        if (query != null) {
            sb.append("\tQuery: ID=").append(query.getId()).append(" Name=").append(query.getName());
            if (StringUtils.isNotBlank(query.getSequence()))
                sb.append(" Sequence=").append(StringUtils.abbreviate(query.getSequence(), 10));
            if (query.getSequenceDatabaseEntry() != null)
                sb.append(" acc=").append(query.getSequenceDatabaseEntry().getAccession());
            sb.append("\n");
        }

        for (Object object : results) {
            BioSequence entity = (BioSequence) object;
            sb.append("\tMatch: ID=").append(entity.getId()).append(" Name=").append(entity.getName());
            if (StringUtils.isNotBlank(entity.getSequence()))
                sb.append(" Sequence=").append(StringUtils.abbreviate(entity.getSequence(), 10));
            if (entity.getSequenceDatabaseEntry() != null)
                sb.append(" acc=").append(entity.getSequenceDatabaseEntry().getAccession());
            sb.append("\n");
        }
        if (AbstractDao.log.isDebugEnabled())
            AbstractDao.log.debug(sb.toString());
    }
}