ubic.gemma.core.expression.experiment.service.ExpressionExperimentSearchServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for ubic.gemma.core.expression.experiment.service.ExpressionExperimentSearchServiceImpl.java

Source

/*
 * The Gemma project
 *
 * Copyright (c) 2009 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.core.expression.experiment.service;

import com.google.common.collect.Sets;
import gemma.gsec.SecurityService;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import ubic.gemma.core.search.SearchResult;
import ubic.gemma.core.search.SearchResultDisplayObject;
import ubic.gemma.core.search.SearchService;
import ubic.gemma.model.analysis.expression.ExpressionExperimentSet;
import ubic.gemma.model.common.search.SearchSettings;
import ubic.gemma.model.common.search.SearchSettingsImpl;
import ubic.gemma.model.expression.experiment.ExpressionExperiment;
import ubic.gemma.model.expression.experiment.ExpressionExperimentSetValueObject;
import ubic.gemma.model.expression.experiment.ExpressionExperimentValueObject;
import ubic.gemma.model.expression.experiment.FreeTextExpressionExperimentResultsValueObject;
import ubic.gemma.model.genome.Taxon;
import ubic.gemma.persistence.service.analysis.expression.coexpression.CoexpressionAnalysisService;
import ubic.gemma.persistence.service.analysis.expression.diff.DifferentialExpressionAnalysisService;
import ubic.gemma.persistence.service.expression.experiment.ExpressionExperimentService;
import ubic.gemma.persistence.service.expression.experiment.ExpressionExperimentSetService;
import ubic.gemma.persistence.service.genome.taxon.TaxonService;
import ubic.gemma.persistence.util.EntityUtils;

import java.util.*;

/**
 * Handles searching for experiments and experiment sets
 *
 * @author tvrossum
 */
@Component
public class ExpressionExperimentSearchServiceImpl implements ExpressionExperimentSearchService {

    private static final Log log = LogFactory.getLog(ExpressionExperimentSearchServiceImpl.class);
    private static final String MASTER_SET_PREFIX = "Master set for";

    private final ExpressionExperimentSetService expressionExperimentSetService;
    private final CoexpressionAnalysisService coexpressionAnalysisService;
    private final DifferentialExpressionAnalysisService differentialExpressionAnalysisService;
    private final SecurityService securityService;
    private final SearchService searchService;
    private final TaxonService taxonService;
    private final ExpressionExperimentService expressionExperimentService;

    @Autowired
    public ExpressionExperimentSearchServiceImpl(ExpressionExperimentSetService expressionExperimentSetService,
            CoexpressionAnalysisService coexpressionAnalysisService,
            DifferentialExpressionAnalysisService differentialExpressionAnalysisService,
            SecurityService securityService, SearchService searchService, TaxonService taxonService,
            ExpressionExperimentService expressionExperimentService) {
        this.expressionExperimentSetService = expressionExperimentSetService;
        this.coexpressionAnalysisService = coexpressionAnalysisService;
        this.differentialExpressionAnalysisService = differentialExpressionAnalysisService;
        this.securityService = securityService;
        this.searchService = searchService;
        this.taxonService = taxonService;
        this.expressionExperimentService = expressionExperimentService;
    }

    @Override
    public Collection<ExpressionExperimentValueObject> searchExpressionExperiments(String query) {

        SearchSettings settings = SearchSettingsImpl.expressionExperimentSearch(query);
        List<SearchResult> experimentSearchResults = searchService.search(settings).get(ExpressionExperiment.class);

        if (experimentSearchResults == null || experimentSearchResults.isEmpty()) {
            ExpressionExperimentSearchServiceImpl.log.info("No experiments for search: " + query);
            return new HashSet<>();
        }

        ExpressionExperimentSearchServiceImpl.log
                .info("Experiment search: " + query + ", " + experimentSearchResults.size() + " found");
        Collection<ExpressionExperimentValueObject> experimentValueObjects = expressionExperimentService
                .loadValueObjects(EntityUtils.getIds(experimentSearchResults), true);
        ExpressionExperimentSearchServiceImpl.log
                .info("Experiment search: " + experimentValueObjects.size() + " value objects returned.");
        return experimentValueObjects;
    }

    @Override
    public Collection<ExpressionExperimentValueObject> searchExpressionExperiments(List<String> query) {

        Set<ExpressionExperimentValueObject> all = new HashSet<>();
        Set<ExpressionExperimentValueObject> prev = null;
        Set<ExpressionExperimentValueObject> current;
        for (String s : query) {
            s = StringUtils.strip(s);
            if (prev == null) {
                prev = new HashSet<>(this.searchExpressionExperiments(s));
                all = new HashSet<>(prev);
                continue;
            }
            current = new HashSet<>(this.searchExpressionExperiments(s));

            all = Sets.intersection(all, current);
        }
        return all;
    }

    @Override
    public List<SearchResultDisplayObject> searchExperimentsAndExperimentGroups(String query, Long taxonId) {

        List<SearchResultDisplayObject> displayResults = new LinkedList<>();

        // if query is blank, return list of public sets, user-owned sets (if logged in) and user's recent
        // session-bound sets (not autogen sets until handling of large searches is fixed)
        if (StringUtils.isBlank(query)) {
            return this.searchExperimentsAndExperimentGroupBlankQuery(taxonId);
        }

        Map<Class<?>, List<SearchResult>> results = this.initialSearch(query, taxonId);

        List<SearchResultDisplayObject> experimentSets = this.getExpressionExperimentSetResults(results);
        List<SearchResultDisplayObject> experiments = this.getExpressionExperimentResults(results);

        if (experimentSets.isEmpty() && experiments.isEmpty()) {
            return displayResults;
        }

        /*
         * ALL RESULTS BY TAXON GROUPS
         */

        // if >1 result, add a group whose members are all experiments returned from search

        Map<Long, Set<Long>> eeIdsByTaxonId = new HashMap<>();

        // add every individual experiment to the set, grouped by taxon and also altogether.
        for (SearchResultDisplayObject srdo : experiments) {

            Long taxId = srdo.getTaxonId();

            if (!eeIdsByTaxonId.containsKey(taxId)) {
                eeIdsByTaxonId.put(taxId, new HashSet<Long>());
            }
            ExpressionExperimentValueObject eevo = (ExpressionExperimentValueObject) srdo.getResultValueObject();
            eeIdsByTaxonId.get(taxId).add(eevo.getId());
        }

        // if there's a group, get the number of members
        // assuming the taxon of the members is the same as that of the group

        // for each group
        for (SearchResultDisplayObject eesSRO : experimentSets) {
            ExpressionExperimentSetValueObject set = (ExpressionExperimentSetValueObject) eesSRO
                    .getResultValueObject();

            /*
             * This is security filtered.
             */
            Collection<Long> ids = EntityUtils
                    .getIds(expressionExperimentSetService.getExperimentValueObjectsInSet(set.getId()));

            set.setSize(ids.size()); // to account for security filtering.

            if (!eeIdsByTaxonId.containsKey(set.getTaxonId())) {
                eeIdsByTaxonId.put(set.getTaxonId(), new HashSet<Long>());
            }
            eeIdsByTaxonId.get(set.getTaxonId()).addAll(ids);
        }

        // make an entry for each taxon

        Long taxonId2;
        for (Map.Entry<Long, Set<Long>> entry : eeIdsByTaxonId.entrySet()) {
            taxonId2 = entry.getKey();
            Taxon taxon = taxonService.load(taxonId2);
            if (taxon != null && entry.getValue().size() > 0) {

                FreeTextExpressionExperimentResultsValueObject ftvo = new FreeTextExpressionExperimentResultsValueObject(
                        "All " + taxon.getCommonName() + " results for '" + query + "'",
                        "All " + taxon.getCommonName() + " experiments found for your query", taxon.getId(),
                        taxon.getCommonName(), entry.getValue(), query);

                int numWithDifferentialExpressionAnalysis = differentialExpressionAnalysisService
                        .getExperimentsWithAnalysis(entry.getValue()).size();

                assert numWithDifferentialExpressionAnalysis <= entry.getValue().size();

                int numWithCoexpressionAnalysis = coexpressionAnalysisService
                        .getExperimentsWithAnalysis(entry.getValue()).size();

                ftvo.setNumWithCoexpressionAnalysis(numWithCoexpressionAnalysis);
                ftvo.setNumWithDifferentialExpressionAnalysis(numWithDifferentialExpressionAnalysis);
                displayResults.add(new SearchResultDisplayObject(ftvo));
            }
        }

        displayResults.addAll(experimentSets);
        displayResults.addAll(experiments);

        if (displayResults.isEmpty()) {
            ExpressionExperimentSearchServiceImpl.log.info("No results for search: " + query);
        } else {
            ExpressionExperimentSearchServiceImpl.log
                    .info("Results for search: " + query + " size=" + displayResults.size() + " entry0: "
                            + ((SearchResultDisplayObject) (displayResults.toArray())[0]).getName()
                            + " valueObject:" + ((SearchResultDisplayObject) (displayResults.toArray())[0])
                                    .getResultValueObject().toString());
        }
        return displayResults;
    }

    @Override
    public List<SearchResultDisplayObject> getAllTaxonExperimentGroup(Long taxonId) {

        List<SearchResultDisplayObject> setResults = new LinkedList<>();

        Taxon taxon = taxonService.load(taxonId);

        Collection<ExpressionExperimentSet> sets = expressionExperimentSetService
                .findByName("Master set for " + taxon.getCommonName().toLowerCase());
        SearchResultDisplayObject newSRDO;
        for (ExpressionExperimentSet set : sets) {
            expressionExperimentSetService.thaw(set);
            if (set.getTaxon().getId().equals(taxonId)) {
                ExpressionExperimentSetValueObject eevo = expressionExperimentSetService.loadValueObject(set);
                newSRDO = new SearchResultDisplayObject(eevo);
                newSRDO.setUserOwned(securityService.isPrivate(set));
                ((ExpressionExperimentSetValueObject) newSRDO.getResultValueObject())
                        .setIsPublic(securityService.isPublic(set));
                setResults.add(newSRDO);
            }
        }

        Collections.sort(setResults);

        return setResults;
    }

    private List<SearchResultDisplayObject> getExpressionExperimentResults(
            Map<Class<?>, List<SearchResult>> results) {
        // get all expressionExperiment results and convert result object into a value object
        List<SearchResult> srEEs = results.get(ExpressionExperiment.class);
        if (srEEs == null) {
            srEEs = new ArrayList<>();
        }

        List<Long> eeIds = new ArrayList<>();
        for (SearchResult sr : srEEs) {
            eeIds.add(sr.getId());
        }

        Collection<ExpressionExperimentValueObject> eevos = expressionExperimentService.loadValueObjects(eeIds,
                true);
        List<SearchResultDisplayObject> experiments = new ArrayList<>();
        for (ExpressionExperimentValueObject eevo : eevos) {
            experiments.add(new SearchResultDisplayObject(eevo));
        }
        return experiments;
    }

    private List<SearchResultDisplayObject> getExpressionExperimentSetResults(
            Map<Class<?>, List<SearchResult>> results) {
        List<SearchResultDisplayObject> experimentSets = new ArrayList<>();

        if (results.get(ExpressionExperimentSet.class) != null) {
            List<Long> eeSetIds = new ArrayList<>();
            for (SearchResult sr : results.get(ExpressionExperimentSet.class)) {
                eeSetIds.add(((ExpressionExperimentSet) sr.getResultObject()).getId());
            }

            if (eeSetIds.isEmpty()) {
                return experimentSets;
            }
            for (ExpressionExperimentSetValueObject eesvo : expressionExperimentSetService
                    .loadValueObjectsByIds(eeSetIds)) {
                experimentSets.add(new SearchResultDisplayObject(eesvo));
            }
        }
        return experimentSets;
    }

    private Map<Class<?>, List<SearchResult>> initialSearch(String query, Long taxonId) {
        SearchSettings settings = SearchSettingsImpl.expressionExperimentSearch(query);
        settings.setSearchExperimentSets(true); // add searching for experimentSets
        Taxon taxonParam;
        if (taxonId != null) {
            taxonParam = taxonService.load(taxonId);
            settings.setTaxon(taxonParam);
        }
        return searchService.search(settings);
    }

    /**
     * if query is blank, return list of public sets, user-owned sets (if logged in) and user's recent session-bound
     * sets called by ubic.gemma.web.controller .expression.experiment.ExpressionExperimentController.
     * searchExperimentsAndExperimentGroup(String, Long) does not include session bound sets
     */
    private List<SearchResultDisplayObject> searchExperimentsAndExperimentGroupBlankQuery(Long taxonId) {
        boolean taxonLimited = taxonId != null;

        List<SearchResultDisplayObject> displayResults = new LinkedList<>();

        // These are widely considered to be the most important results and
        // therefore need to be at the top
        List<SearchResultDisplayObject> masterResults = new LinkedList<>();

        Collection<ExpressionExperimentSetValueObject> evos = expressionExperimentSetService
                .loadAllExperimentSetValueObjects(true);

        for (ExpressionExperimentSetValueObject evo : evos) {

            if (taxonLimited && !evo.getTaxonId().equals(taxonId)) {
                continue;
            }

            SearchResultDisplayObject srdvo = new SearchResultDisplayObject(evo);
            if (evo.getName().startsWith(ExpressionExperimentSearchServiceImpl.MASTER_SET_PREFIX)) {
                masterResults.add(srdvo);
            } else {
                displayResults.add(srdvo);
            }
        }

        Collections.sort(displayResults);

        // should we also sort by which species is most important(humans obviously) or is that not politically
        // correct???
        displayResults.addAll(0, masterResults);

        return displayResults;
    }
}