org.obiba.mica.search.csvexport.SpecificStudyReportGenerator.java Source code

Java tutorial

Introduction

Here is the source code for org.obiba.mica.search.csvexport.SpecificStudyReportGenerator.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.csvexport;

import au.com.bytecode.opencsv.CSVWriter;
import org.obiba.core.translator.JsonTranslator;
import org.obiba.core.translator.Translator;
import org.obiba.mica.core.domain.LocalizedString;
import org.obiba.mica.micaConfig.service.MicaConfigService;
import org.obiba.mica.network.service.NetworkService;
import org.obiba.mica.search.JoinQueryExecutor;
import org.obiba.mica.search.csvexport.generators.CsvReportGeneratorImpl;
import org.obiba.mica.spi.search.QueryType;
import org.obiba.mica.spi.search.Searcher;
import org.obiba.mica.spi.search.support.JoinQuery;
import org.obiba.mica.study.domain.BaseStudy;
import org.obiba.mica.study.domain.Population;
import org.obiba.mica.study.service.PublishedStudyService;
import org.obiba.mica.study.service.StudyService;
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 org.springframework.util.StringUtils;

import javax.inject.Inject;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.function.Function;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

@Component
@Scope("request")
public class SpecificStudyReportGenerator extends CsvReportGeneratorImpl {

    private static final Logger logger = LoggerFactory.getLogger(SpecificStudyReportGenerator.class);

    @Inject
    private JoinQueryExecutor joinQueryExecutor;

    @Inject
    private Searcher searcher;

    @Inject
    private MicaConfigService micaConfigService;

    @Inject
    private PublishedStudyService publishedStudyService;

    @Inject
    private StudyService studyService;

    @Inject
    private NetworkService networkService;

    private Translator translator;
    private List<String> studyIds;
    private String locale;

    public void report(Translator translator, List<String> studyIds, String locale, OutputStream outputStream) {
        this.translator = translator;
        this.studyIds = studyIds.stream().sorted().collect(toList());
        this.locale = locale;
        this.write(outputStream);
    }

    public void report(String networkId, String locale, OutputStream outputStream) throws IOException {
        List<String> studyIds = networkService.findById(networkId).getStudyIds();
        Translator translator = JsonTranslator
                .buildSafeTranslator(() -> micaConfigService.getTranslations(locale, false));

        report(translator, studyIds, locale, outputStream);
    }

    public void report(String rqlQuery, OutputStream outputStream) throws IOException {

        JoinQuery joinQuery = searcher.makeJoinQuery(rqlQuery);

        List<String> studyIds = joinQueryExecutor.query(QueryType.STUDY, joinQuery).getStudyResultDto()
                .getExtension(MicaSearch.StudyResultDto.result).getSummariesList().stream()
                .map(Mica.StudySummaryDto::getId).collect(toList());
        Translator translator = JsonTranslator
                .buildSafeTranslator(() -> micaConfigService.getTranslations(joinQuery.getLocale(), false));

        report(translator, studyIds, joinQuery.getLocale(), outputStream);
    }

    @Override
    protected void writeHeader(CSVWriter writer) {

        List<String> line = new ArrayList<>();

        line.add(tr("report-group.study.name"));
        line.add(tr("report-group.study.acronym"));
        line.add(tr("report-group.study.type"));
        line.add(tr("report-group.study.status"));
        line.add(tr("report-group.study.country"));
        line.add(tr("report-group.study.start-year"));
        line.add(tr("report-group.study.years-of-follow-up"));
        line.add(tr("report-group.study.study-design"));
        line.add(tr("report-group.study.recruitment-target"));
        line.add(tr("report-group.study.number-of-participants"));
        line.add(tr("report-group.study.number-of-bio-samples"));
        line.add(tr("report-group.study.population.name"));
        line.add(tr("report-group.study.population.source-of-recruitment"));
        line.add(tr("report-group.study.population.minimum-age"));
        line.add(tr("report-group.study.population.maximum-age"));
        line.add(tr("report-group.study.population.number-of-participants"));
        line.add(tr("report-group.study.population.number-of-bio-samples"));
        line.add(tr("report-group.study.population.number-of-data-collection-events"));

        writer.writeNext(line.toArray(new String[line.size()]));
    }

    @Override
    protected void writeEachLine(CSVWriter writer) {

        for (String studyId : studyIds) {
            BaseStudy publishedStudy = publishedStudyService.findById(studyId);

            if (publishedStudy != null) {

                List<String> publishedStudyDetails = generatePublishedStudyDetails(publishedStudy);

                Iterator<Population> populationIterator = publishedStudy.getPopulations().iterator();

                if (!populationIterator.hasNext()) {
                    writer.writeNext(publishedStudyDetails.toArray(new String[publishedStudyDetails.size()]));
                }

                while (populationIterator.hasNext()) {
                    List<String> buildingCompleteLine = new ArrayList<>(publishedStudyDetails);
                    Population next = populationIterator.next();
                    buildingCompleteLine.addAll(generatePopulationDetails(next));
                    writer.writeNext(buildingCompleteLine.toArray(new String[buildingCompleteLine.size()]));
                }
            } else {

                BaseStudy draftStudy = studyService.findStudy(studyId);
                if (draftStudy != null) {
                    List<String> lineOfDratStudy = generateDraftStudyDetails(draftStudy);
                    writer.writeNext(lineOfDratStudy.toArray(new String[lineOfDratStudy.size()]));
                }
            }
        }
    }

    private Map<String, Locale> getCountries() {
        return Arrays.stream(Locale.getAvailableLocales()).collect(Collectors.toMap(locale -> {
            try {
                return locale.getISO3Country();
            } catch (RuntimeException e) {
                return locale.getCountry();
            }
        }, Function.identity(), (a, b) -> a));
    }

    private String getCountryName(String iso3Country) {
        try {
            return getCountries().get(iso3Country).getDisplayCountry(new Locale(this.locale));
        } catch (RuntimeException e) {
            logger.debug("Translation of country %s is not available in java database", e);
            return iso3Country;
        }
    }

    private List<String> generateDraftStudyDetails(BaseStudy study) {
        List<String> line = new ArrayList<>();

        line.add(localizedField(study::getName));
        line.add(localizedField(study::getAcronym));
        line.add(field(() -> tr("global." + study.getResourcePath())));
        line.add(field(() -> tr("draft")));

        return line;
    }

    private List<String> generatePublishedStudyDetails(BaseStudy study) {
        List<String> line = new ArrayList<>();

        line.add(localizedField(study::getName));
        line.add(localizedField(study::getAcronym));
        line.add(field(() -> tr("global." + study.getResourcePath())));
        line.add(field(() -> tr("published")));
        line.add(arrayField(() -> study.getPopulations().stream().flatMap(population -> {
            Map<String, List<String>> selectionCriteria = (Map<String, List<String>>) population.getModel()
                    .get("selectionCriteria");
            return selectionCriteria.get("countriesIso").stream().map(this::getCountryName);
        }).distinct().sorted().collect(toList())));
        line.add(field(() -> study.getModel().get("startYear").toString()));
        line.add(field(() -> calculateYearsOfFollowUp(study)));
        line.add(field(() -> tr("study_taxonomy.vocabulary.methods-design.term."
                + ((Map<String, Object>) study.getModel().get("methods")).get("design").toString() + ".title")));
        line.add(arrayField(
                () -> ((List<String>) ((Map<String, Object>) study.getModel().get("methods")).get("recruitments"))
                        .stream()
                        .map(m -> tr("study_taxonomy.vocabulary.methods-recruitments.term." + m + ".title"))
                        .sorted().collect(toList())));
        line.add(field(
                () -> ((Map<String, Object>) ((Map<String, Object>) study.getModel().get("numberOfParticipants"))
                        .get("participant")).get("number").toString()));
        line.add(field(
                () -> ((Map<String, Object>) ((Map<String, Object>) study.getModel().get("numberOfParticipants"))
                        .get("sample")).get("number").toString()));

        return line;
    }

    @NotNull
    private List<String> generatePopulationDetails(Population population) {
        List<String> line = new ArrayList<>();

        line.add(localizedField(() -> population.getName()));
        line.add(arrayField(() -> ((List<String>) ((Map<String, Object>) population.getModel().get("recruitment"))
                .get("dataSources")).stream().map(source -> tr(
                        "study_taxonomy.vocabulary.populations-recruitment-dataSources.term." + source + ".title"))
                        .sorted().collect(toList())));
        line.add(field(() -> ((Map<String, Object>) population.getModel().get("selectionCriteria")).get("ageMin")
                .toString()));
        line.add(field(() -> ((Map<String, Object>) population.getModel().get("selectionCriteria")).get("ageMax")
                .toString()));
        line.add(field(() -> ((Map<String, Object>) ((Map<String, Object>) population.getModel()
                .get("numberOfParticipants")).get("participant")).get("number").toString()));
        line.add(field(() -> ((Map<String, Object>) ((Map<String, Object>) population.getModel()
                .get("numberOfParticipants")).get("sample")).get("number").toString()));
        line.add(field(() -> Integer.toString(population.getDataCollectionEvents().size())));

        return line;
    }

    private String calculateYearsOfFollowUp(BaseStudy studySummaryDto) {
        if (studySummaryDto.getModel().get("startYear") == null)
            return "";
        int startYear = (int) studySummaryDto.getModel().get("startYear");
        int endYear = studySummaryDto.getModel().get("endYear") != null
                ? (int) studySummaryDto.getModel().get("endYear")
                : Calendar.getInstance().get(Calendar.YEAR);
        return Integer.toString(endYear - startYear);
    }

    private String tr(String key) {
        return translator.translate(key);
    }

    private String field(Callable<String> field) {
        try {
            return field.call();
        } catch (Exception e) {
            logger.debug("Error while generating csv custom report", e);
            return "";
        }
    }

    private String localizedField(Callable<LocalizedString> field) {
        return field(() -> field.call().get(this.locale));
    }

    private String arrayField(final Callable<List<String>> field) {
        return field(() -> {
            List<String> fields = field.call();
            return StringUtils.arrayToDelimitedString(fields.toArray(new String[fields.size()]), ", ");
        });
    }
}