org.obiba.mica.search.queries.NetworkQuery.java Source code

Java tutorial

Introduction

Here is the source code for org.obiba.mica.search.queries.NetworkQuery.java

Source

/*
 * Copyright (c) 2018 OBiBa. All rights reserved.
 *
 * This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.obiba.mica.search.queries;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.obiba.mica.micaConfig.service.helper.AggregationMetaDataProvider;
import org.obiba.mica.network.domain.Network;
import org.obiba.mica.network.domain.NetworkState;
import org.obiba.mica.network.service.PublishedNetworkService;
import org.obiba.mica.search.aggregations.NetworkAggregationMetaDataProvider;
import org.obiba.mica.search.aggregations.NetworkTaxonomyMetaDataProvider;
import org.obiba.mica.spi.search.CountStatsData;
import org.obiba.mica.spi.search.Indexer;
import org.obiba.mica.spi.search.QueryMode;
import org.obiba.mica.spi.search.QueryScope;
import org.obiba.mica.spi.search.Searcher;
import org.obiba.mica.web.model.Dtos;
import org.obiba.mica.web.model.Mica;
import org.obiba.mica.web.model.MicaSearch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.Nullable;
import javax.inject.Inject;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import static org.obiba.mica.search.CountStatsDtoBuilders.NetworkCountStatsBuilder;
import static org.obiba.mica.web.model.MicaSearch.NetworkResultDto;
import static org.obiba.mica.web.model.MicaSearch.QueryResultDto;

@Component
@Scope("request")
public class NetworkQuery extends AbstractDocumentQuery {

    private static final Logger log = LoggerFactory.getLogger(NetworkQuery.class);

    public static final String JOIN_FIELD = "studyIds";

    @Inject
    Dtos dtos;

    @Inject
    PublishedNetworkService publishedNetworkService;

    @Inject
    private NetworkAggregationMetaDataProvider networkAggregationMetaDataProvider;

    @Inject
    private NetworkTaxonomyMetaDataProvider networkTaxonomyMetaDataProvider;

    @Override
    public String getSearchIndex() {
        return Indexer.PUBLISHED_NETWORK_INDEX;
    }

    @Override
    public String getSearchType() {
        return Indexer.NETWORK_TYPE;
    }

    @Nullable
    @Override
    protected Searcher.IdFilter getAccessibleIdFilter() {
        if (isOpenAccess())
            return null;
        return new Searcher.IdFilter() {
            @Override
            public Collection<String> getValues() {
                return publishedNetworkService.getNetworkService().findPublishedIds().stream()
                        .filter(s -> subjectAclService.isAccessible("/network", s)).collect(Collectors.toList());
            }
        };
    }

    @Nullable
    @Override
    protected Properties getAggregationsProperties(List<String> filter) {
        Properties properties = getAggregationsProperties(filter, taxonomyService.getNetworkTaxonomy());
        if (!properties.containsKey(JOIN_FIELD))
            properties.put(JOIN_FIELD, "");
        return properties;
    }

    @Override
    public void processHits(QueryResultDto.Builder builder, Searcher.DocumentResults results, QueryScope scope,
            CountStatsData counts) throws IOException {
        NetworkResultDto.Builder resBuilder = NetworkResultDto.newBuilder();
        NetworkCountStatsBuilder networkCountStatsBuilder = counts == null ? null
                : NetworkCountStatsBuilder.newBuilder(counts);

        Consumer<Network> addDto = networkConsumer(scope, resBuilder, networkCountStatsBuilder);
        List<Network> networks = Lists.newArrayList();

        for (Searcher.DocumentResult result : results.getDocuments()) {
            if (result.hasSource())
                networks.add(objectMapper.readValue(result.getSourceInputStream(), Network.class));
        }

        networks.forEach(addDto);
        builder.setExtension(NetworkResultDto.result, resBuilder.build());
    }

    private Consumer<Network> networkConsumer(QueryScope scope, NetworkResultDto.Builder resBuilder,
            NetworkCountStatsBuilder networkCountStatsBuilder) {

        return scope == QueryScope.DETAIL ? networkConsumer(resBuilder, networkCountStatsBuilder)
                : (network) -> resBuilder.addDigests(dtos.asDigestDtoBuilder(network).build());
    }

    private Consumer<Network> networkConsumer(NetworkResultDto.Builder resBuilder,
            NetworkCountStatsBuilder networkCountStatsBuilder) {
        return (network) -> {
            Mica.NetworkDto.Builder networkBuilder = dtos.asDtoBuilder(network);
            if (mode == QueryMode.LIST) {
                networkBuilder.clearStudySummaries();
                networkBuilder.clearContacts();
                networkBuilder.clearInvestigators();
            }
            if (networkCountStatsBuilder != null) {
                networkBuilder.setExtension(MicaSearch.CountStatsDto.networkCountStats,
                        networkCountStatsBuilder.build(network)).build();
            }
            resBuilder.addNetworks(networkBuilder.build());
        };
    }

    @Override
    protected List<String> getMandatorySourceFields() {
        return Lists.newArrayList("id");
    }

    @Override
    protected List<String> getJoinFields() {
        return Arrays.asList(JOIN_FIELD);
    }

    @Override
    protected List<AggregationMetaDataProvider> getAggregationMetaDataProviders() {
        return Arrays.asList(networkAggregationMetaDataProvider, networkTaxonomyMetaDataProvider);
    }

    public Map<String, List<String>> getStudyCountsByNetwork() {
        Map<String, List<String>> map = Maps.newHashMap();
        if (!micaConfigService.getConfig().isNetworkEnabled())
            return map;

        Properties props = new Properties();
        props.setProperty("id", "");
        Properties subProps = new Properties();
        subProps.setProperty(JOIN_FIELD, "");
        Map<String, Properties> subAggregations = Maps.newHashMap();
        subAggregations.put("id", subProps);

        try {
            Searcher.DocumentResults results = searcher.cover(getSearchIndex(), getSearchType(), getQuery(), props,
                    subAggregations, null);
            results.getAggregations().stream().filter(agg -> "terms".equals(agg.getType()))
                    .forEach(aggregation -> aggregation.asTerms().getBuckets().stream()
                            .filter(bucket -> bucket.getDocCount() > 0).forEach(bucket -> map
                                    .put(bucket.getKeyAsString(), getStudyCounts(bucket.getAggregations()))));
        } catch (Exception e) {
            log.warn("Study counts by network failed", e);
        }
        return map;
    }

    private List<String> getStudyCounts(List<Searcher.DocumentAggregation> aggregations) {
        List<String> list = Lists.newArrayList();
        aggregations.stream().filter(agg -> "terms".equals(agg.getType()))
                .forEach(aggregation -> aggregation.asTerms().getBuckets().stream()
                        .filter(bucket -> bucket.getDocCount() > 0)
                        .forEach(bucket -> list.add(bucket.getKeyAsString())));
        return list;
    }

    @Override
    public Map<String, Integer> getStudyCounts() {
        return getDocumentCounts(JOIN_FIELD);
    }
}