001/*
002 * The contents of this file are subject to the license and copyright
003 * detailed in the LICENSE and NOTICE files at the root of the source
004 * tree.
005 */
006package org.fcrepo.stats.impl;
007
008import java.util.ArrayList;
009import java.util.List;
010
011import javax.annotation.PostConstruct;
012import javax.inject.Inject;
013import javax.sql.DataSource;
014
015import org.fcrepo.kernel.api.RdfLexicon;
016import org.fcrepo.stats.api.MimeTypeStatsResult;
017import org.fcrepo.stats.api.RdfTypeStatsResult;
018import org.fcrepo.stats.api.RepositoryStats;
019import org.fcrepo.stats.api.RepositoryStatsByMimeTypeResults;
020import org.fcrepo.stats.api.RepositoryStatsByRdfTypeResults;
021import org.fcrepo.stats.api.RepositoryStatsParameters;
022import org.fcrepo.stats.api.RepositoryStatsResult;
023import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
024import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
025import org.springframework.jdbc.support.rowset.SqlRowSet;
026import org.springframework.stereotype.Component;
027import org.springframework.util.CollectionUtils;
028
029/**
030 * A database-backed implementation of the <code>RepositoryStats</code> interface.
031 * It depends on the tables that drive the search index.
032 *
033 * @author dbernstein
034 */
035@Component("stats")
036public class DbRepositoryStatsImpl implements RepositoryStats {
037
038    private static final String SELECT_COUNT_FROM_SIMPLE_SEARCH = "select count(*) from simple_search";
039
040    @Inject
041    private DataSource dataSource;
042
043    private NamedParameterJdbcTemplate jdbcTemplate;
044
045    /**
046     * Setup template
047     */
048    @PostConstruct
049    public void setup() {
050        this.jdbcTemplate = new NamedParameterJdbcTemplate(this.dataSource);
051    }
052
053
054    @Override
055    public RepositoryStatsResult getResourceCount(final RepositoryStatsParameters statsParams) {
056        final var parameterSource = new MapSqlParameterSource();
057        final var results = jdbcTemplate.queryForRowSet(SELECT_COUNT_FROM_SIMPLE_SEARCH, parameterSource);
058        results.first();
059        final var result = new RepositoryStatsResult();
060        result.setResourceCount(results.getLong(1));
061        return result;
062    }
063
064    @Override
065    public RepositoryStatsByMimeTypeResults getByMimeTypes(final RepositoryStatsParameters statsParams) {
066        final var results = new RepositoryStatsByMimeTypeResults();
067        final var mimeTypes = statsParams.getMimeTypes();
068        final var parameterSource = new MapSqlParameterSource();
069        final var mimeTypesQuery = formatMimetypeQuery(mimeTypes, parameterSource);
070        final var mimetypeResults = jdbcTemplate.queryForRowSet(mimeTypesQuery, parameterSource);
071        marshallMimeTypeResults(results, mimetypeResults);
072        return results;
073    }
074
075    @Override
076    public RepositoryStatsByRdfTypeResults getByRdfType(final RepositoryStatsParameters statsParams) {
077        final var results = new RepositoryStatsByRdfTypeResults();
078        final var parameterSource = new MapSqlParameterSource();
079        final var query = formatRdfTypeQuery(statsParams.getRdfTypes(), parameterSource);
080        final var rdfTypeResults = jdbcTemplate.queryForRowSet(query, parameterSource);
081        marshallRdfTypeResults(results, rdfTypeResults);
082        return results;
083    }
084
085    private void marshallMimeTypeResults(final RepositoryStatsByMimeTypeResults results,
086                                         final SqlRowSet mimeTypeResults) {
087        if (mimeTypeResults.first()) {
088            final var mimeTypesResultList = new ArrayList<MimeTypeStatsResult>();
089            do {
090                final var mimeTypeResult = new MimeTypeStatsResult();
091                mimeTypeResult.setMimeType(mimeTypeResults.getString(1));
092                mimeTypeResult.setResourceCount(mimeTypeResults.getLong(2));
093                mimeTypeResult.setByteCount(mimeTypeResults.getLong(3));
094                mimeTypesResultList.add(mimeTypeResult);
095            } while (mimeTypeResults.next());
096            results.setMimeTypes(mimeTypesResultList);
097        }
098    }
099
100    private String formatMimetypeQuery(final List<String> mimeTypes, final MapSqlParameterSource parameterSource) {
101        final var mimeTypesQuery = new StringBuilder("select a.mime_type, count(a.id), sum(a.content_size) ");
102        mimeTypesQuery.append("from simple_search a, search_resource_rdf_type b,  search_rdf_type c ");
103        mimeTypesQuery.append("where a.id = b.resource_id and b.rdf_type_id = c.id and c.rdf_type_uri = '");
104        mimeTypesQuery.append(RdfLexicon.NON_RDF_SOURCE.getURI());
105        mimeTypesQuery.append("' ");
106        if (!CollectionUtils.isEmpty(mimeTypes)) {
107            mimeTypesQuery.append("and a.mime_type in (:mime_types) ");
108            parameterSource.addValue("mime_types", mimeTypes);
109        }
110        mimeTypesQuery.append("group by a.mime_type order by a.mime_type");
111        return mimeTypesQuery.toString();
112    }
113
114    private void marshallRdfTypeResults(final RepositoryStatsByRdfTypeResults results,
115                                        final SqlRowSet rdfTypeResults) {
116        if (rdfTypeResults.first()) {
117            final var resourceTypeStatsResults = new ArrayList<RdfTypeStatsResult>();
118            do {
119                final var resourceTypeResult = new RdfTypeStatsResult();
120                resourceTypeResult.setResourceType(rdfTypeResults.getString(1));
121                resourceTypeResult.setResourceCount(rdfTypeResults.getLong(2));
122                resourceTypeResult.setByteCount(rdfTypeResults.getLong(3));
123                resourceTypeStatsResults.add(resourceTypeResult);
124            } while (rdfTypeResults.next());
125            results.setRdfTypes(resourceTypeStatsResults);
126        }
127    }
128
129
130    private String formatRdfTypeQuery(final List<String> rdfTypes, final MapSqlParameterSource parameterSource) {
131        final var rdfTypesQuery = new StringBuilder(
132                "select c.rdf_type_uri, count(b.resource_id), sum(a.content_size) ");
133        rdfTypesQuery.append("from simple_search a, search_resource_rdf_type b,  search_rdf_type c ");
134        rdfTypesQuery.append("where a.id = b.resource_id and b.rdf_type_id = c.id ");
135        if (!CollectionUtils.isEmpty(rdfTypes)) {
136            rdfTypesQuery.append("and c.rdf_type_uri in (:rdf_types) ");
137            parameterSource.addValue("rdf_types", rdfTypes);
138        }
139        rdfTypesQuery.append("group by c.rdf_type_uri");
140        return rdfTypesQuery.toString();
141    }
142}