Package org.zanata.dao

Source Code of org.zanata.dao.DocumentDAO

package org.zanata.dao;

import java.sql.Timestamp;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

import org.hibernate.LobHelper;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.type.TimestampType;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.zanata.common.ContentState;
import org.zanata.common.LocaleId;
import org.zanata.common.TransUnitCount;
import org.zanata.common.TransUnitWords;
import org.zanata.file.GlobalDocumentId;
import org.zanata.model.HDocument;
import org.zanata.model.HLocale;
import org.zanata.model.HProjectIteration;
import org.zanata.model.HRawDocument;
import org.zanata.model.HTextFlowTarget;
import org.zanata.model.StatusCount;
import org.zanata.rest.dto.stats.ContainerTranslationStatistics;
import org.zanata.rest.dto.stats.TranslationStatistics;
import org.zanata.rest.dto.stats.TranslationStatistics.StatUnit;
import org.zanata.ui.model.statistic.WordStatistic;
import org.zanata.util.StatisticsUtil;
import com.google.common.base.Optional;

import lombok.extern.slf4j.Slf4j;

@Name("documentDAO")
@AutoCreate
@Scope(ScopeType.STATELESS)
@Slf4j
public class DocumentDAO extends AbstractDAOImpl<HDocument, Long> {
    public DocumentDAO() {
        super(HDocument.class);
    }

    public DocumentDAO(Session session) {
        super(HDocument.class, session);
    }

    public @Nullable
    HDocument getByDocIdAndIteration(HProjectIteration iteration, String id) {
        return (HDocument) getSession().byNaturalId(HDocument.class)
                .using("docId", id).using("projectIteration", iteration).load();
    }

    public HDocument getById(Long id) {
        return (HDocument) getSession().get(HDocument.class, id);
    }

    public Set<LocaleId> getTargetLocales(HDocument hDoc) {
        // TODO should this use UNIQUE?
        Query q =
                getSession().createQuery(
                        "select tft.locale from HTextFlowTarget tft "
                                + "where tft.textFlow.document = :document");
        q.setParameter("document", hDoc);
        q.setComment("DocumentDAO.getTargetLocales");
        // TODO q.setCacheable(true); ??
        @SuppressWarnings("unchecked")
        List<LocaleId> locales = q.list();
        return new HashSet<LocaleId>(locales);
    }

    public int getTotalDocument() {
        Query q = getSession().createQuery("select count(*) from HDocument");
        q.setCacheable(true);
        q.setComment("DocumentDAO.getTotalDocument");
        Long totalCount = (Long) q.uniqueResult();
        if (totalCount == null)
            return 0;
        return totalCount.intValue();
    }

    public int getTotalActiveDocument() {
        Query q =
                getSession().createQuery(
                        "select count(*) from HDocument doc "
                                + "where doc.obsolete = false");
        q.setCacheable(true);
        q.setComment("DocumentDAO.getTotalActiveDocument");
        Long totalCount = (Long) q.uniqueResult();
        if (totalCount == null)
            return 0;
        return totalCount.intValue();
    }

    public int getTotalObsoleteDocument() {
        Query q =
                getSession().createQuery(
                        "select count(*) from HDocument doc "
                                + "where doc.obsolete = true");
        q.setCacheable(true);
        q.setComment("DocumentDAO.getTotalObsoleteDocument");
        Long totalCount = (Long) q.uniqueResult();
        if (totalCount == null)
            return 0;
        return totalCount.intValue();
    }

    /**
     * Returns the total message count for a document
     */
    public Long getTotalCountForDocument(Long documentId) {
        Session session = getSession();
        Long totalCount =
                (Long) session
                        .createQuery(
                                "select count(tf) from HTextFlow tf "
                                        + "where tf.document.id = :docId "
                                        + "and tf.obsolete = false")
                        .setParameter("docId", documentId)
                        .setComment("DocumentDAO.getTotalCountForDocument")
                        .setCacheable(true).uniqueResult();

        if (totalCount == null) {
            totalCount = 0L;
        }

        return totalCount;

    }

    public Long getTotalWordCountForDocument(Long documentId) {
        Session session = getSession();

        Long totalWordCount =
                (Long) session
                        .createQuery(
                                "select sum(tf.wordCount) from HTextFlow tf "
                                        + "where tf.document.id = :documentId "
                                        + "and tf.obsolete = false")
                        .setParameter("documentId", documentId)
                        .setCacheable(true)
                        .setComment("DocumentDAO.getTotalWordCountForDocument")
                        .uniqueResult();

        if (totalWordCount == null) {
            totalWordCount = 0L;
        }

        return totalWordCount;

    }

    public HTextFlowTarget getLastTranslatedTarget(Long documentId,
            LocaleId localeId) {
        Session session = getSession();

        StringBuilder query = new StringBuilder();

        query.append("from HTextFlowTarget tft ");
        query.append("where tft.textFlow.document.id = :docId ");
        query.append("and tft.locale.localeId = :localeId ");
        query.append("order by tft.lastChanged DESC");

        return (HTextFlowTarget) session.createQuery(query.toString())
                .setParameter("docId", documentId)
                .setParameter("localeId", localeId).setCacheable(true)
                .setMaxResults(1).setComment("DocumentDAO.getLastTranslated")
                .uniqueResult();
    }

    @Nullable
    public HTextFlowTarget getLastTranslatedTargetOrNull(Long documentId) {
        Session session = getSession();

        StringBuilder query = new StringBuilder();

        query.append("from HTextFlowTarget tft ");
        query.append("where tft.textFlow.document.id = :docId ");
        query.append("order by tft.lastChanged DESC");

        return (HTextFlowTarget) session.createQuery(query.toString())
                .setParameter("docId", documentId).setCacheable(true)
                .setMaxResults(1).setComment("DocumentDAO.getLastTranslated")
                .uniqueResult();
    }

    public WordStatistic getWordStatistics(Long documentId, LocaleId localeId) {
        WordStatistic wordStatistic = new WordStatistic();

        List<StatusCount> stats = getWordStatusCount(documentId, localeId);

        for (StatusCount count : stats) {
            wordStatistic.set(count.status, count.count.intValue());
        }

        Long totalCount = getTotalWordCountForDocument(documentId);
        wordStatistic.set(
                ContentState.New,
                totalCount.intValue()
                        - (wordStatistic.getApproved()
                                + wordStatistic.getTranslated()
                                + wordStatistic.getNeedReview() + wordStatistic
                                    .getRejected()));

        return wordStatistic;
    }

    public List<StatusCount> getWordStatusCount(Long documentId,
            LocaleId localeId) {
        Query q =
                getSession()
                        .createQuery(
                                "select new org.zanata.model.StatusCount(tft.state, "
                                        + "sum(tft.textFlow.wordCount)) "
                                        + "from HTextFlowTarget tft "
                                        + "where tft.textFlow.document.id = :documentId "
                                        + "and tft.locale.localeId = :localeId "
                                        + "and tft.textFlow.obsolete = false "
                                        + "and tft.textFlow.document.obsolete = false "
                                        + "group by tft.state ");
        q.setParameter("documentId", documentId).setParameter("localeId",
                localeId);
        q.setCacheable(true).setComment("DocumentDAO.getWordStatistics");
        @SuppressWarnings("unchecked")
        List<StatusCount> stats = q.list();
        return stats;
    }

    /**
     * @see ProjectIterationDAO#getStatisticsForContainer(Long, LocaleId)
     * @param docId
     * @param localeId
     * @return
     */
    public ContainerTranslationStatistics getStatistics(long docId,
            LocaleId localeId) {
        Session session = getSession();

        // calculate unit counts
        @SuppressWarnings("unchecked")
        List<StatusCount> stats =
                session.createQuery(
                        "select new org.zanata.model.StatusCount("
                                + "tft.state, count(tft)) "
                                + "from HTextFlowTarget tft "
                                + "where tft.textFlow.document.id = :id "
                                + "  and tft.locale.localeId = :locale "
                                + "  and tft.textFlow.obsolete = false "
                                + "group by tft.state")
                        .setParameter("id", docId)
                        .setParameter("locale", localeId)
                        .setComment("DocumentDAO.getStatistics-units")
                        .setCacheable(true).list();
        Long totalCount = getTotalCountForDocument(docId);

        TransUnitCount unitCount = new TransUnitCount();
        for (StatusCount count : stats) {
            unitCount.set(count.status, count.count.intValue());
        }
        unitCount.set(ContentState.New,
                StatisticsUtil.calculateUntranslated(totalCount, unitCount));

        // calculate word counts
        @SuppressWarnings("unchecked")
        List<StatusCount> wordStats =
                session.createQuery(
                        "select new org.zanata.model.StatusCount("
                                + "tft.state, sum(tft.textFlow.wordCount)) "
                                + "from HTextFlowTarget tft "
                                + "where tft.textFlow.document.id = :id "
                                + "  and tft.locale.localeId = :locale "
                                + "  and tft.textFlow.obsolete = false "
                                + "group by tft.state")
                        .setParameter("id", docId)
                        .setParameter("locale", localeId).setCacheable(true)
                        .setComment("DocumentDAO.getStatistics-words").list();
        Long totalWordCount = getTotalWordCountForDocument(docId);
        TransUnitWords wordCount = new TransUnitWords();
        for (StatusCount count : wordStats) {
            wordCount.set(count.status, count.count.intValue());
        }
        long newWordCount =
                StatisticsUtil.calculateUntranslated(totalWordCount, wordCount);
        wordCount.set(ContentState.New, (int) newWordCount);

        ContainerTranslationStatistics result =
                new ContainerTranslationStatistics();
        result.addStats(new TranslationStatistics(unitCount, localeId
                .toString()));
        result.addStats(new TranslationStatistics(wordCount, localeId
                .toString()));

        return result;
    }

    /**
     *
     * This method is currently returning wrong statistics -
     * https://bugzilla.redhat.com/show_bug.cgi?id=1064737 Returns document
     * statistics for multiple locales.
     *
     * @see DocumentDAO#getStatistics(long, org.zanata.common.LocaleId)
     * @param docId
     * @param localeIds
     *            If empty or null, data for all locales will be returned.
     * @return Map of document statistics indexed by locale. Some locales may
     *         not have entries if there is no data stored for them.
     */
    public Map<LocaleId, ContainerTranslationStatistics> getStatistics(
            long docId, LocaleId... localeIds) {
        Session session = getSession();
        Map<LocaleId, ContainerTranslationStatistics> returnStats =
                new HashMap<LocaleId, ContainerTranslationStatistics>();
        Map<String, TransUnitCount> transUnitCountMap =
                new HashMap<String, TransUnitCount>();
        Map<String, TransUnitWords> transUnitWordsMap =
                new HashMap<String, TransUnitWords>();

        StringBuilder query = new StringBuilder();
        query.append("select new map (tft.state as state, count(tft) as msgCount, ");
        query.append("          sum(tft.textFlow.wordCount) as wordCount, "
                + "tft.locale.localeId as locale) ");
        query.append("from HTextFlowTarget tft ");
        query.append("where tft.textFlow.document.id = :id ");
        if (localeIds != null && localeIds.length > 0) {
            query.append("  and tft.locale.localeId in (:locales) ");
        }
        query.append("  and tft.textFlow.obsolete = false ");
        query.append("group by tft.state, tft.locale");

        // calculate unit counts
        @SuppressWarnings("unchecked")
        Query hQuery =
                session.createQuery(query.toString())
                        .setParameter("id", docId)
                        .setComment(
                                "DocumentDAO.getStatisticsMultipleLocales-units")
                        .setCacheable(true);

        if (localeIds != null && localeIds.length > 0) {
            hQuery.setParameterList("locales", localeIds);
        }

        List<Map<String, Object>> stats = hQuery.list();
        // Collect the results for all states
        for (Map<String, Object> row : stats) {
            ContentState state = (ContentState) row.get("state");
            Long msgCount = (Long) row.get("msgCount");
            Long wordCount = (Long) row.get("wordCount");
            LocaleId localeId = (LocaleId) row.get("locale");

            TransUnitCount transUnitCount =
                    transUnitCountMap.get(localeId.getId());
            if (transUnitCount == null) {
                transUnitCount = new TransUnitCount();
                transUnitCountMap.put(localeId.getId(), transUnitCount);
            }

            TransUnitWords transUnitWords =
                    transUnitWordsMap.get(localeId.getId());
            if (transUnitWords == null) {
                transUnitWords = new TransUnitWords();
                transUnitWordsMap.put(localeId.getId(), transUnitWords);
            }

            transUnitCount.set(state, msgCount.intValue());
            transUnitWords.set(state, wordCount.intValue());
        }

        for (TransUnitCount stat : transUnitCountMap.values()) {
            stat.set(
                    ContentState.New,
                    StatisticsUtil.calculateUntranslated(
                            new Long(stat.getTotal()), stat));
        }
        for (TransUnitWords stat : transUnitWordsMap.values()) {
            stat.set(
                    ContentState.New,
                    StatisticsUtil.calculateUntranslated(
                            new Long(stat.getTotal()), stat));
        }

        // Merge into a single Stats object
        for (String locale : transUnitCountMap.keySet()) {
            ContainerTranslationStatistics newStats =
                    new ContainerTranslationStatistics();
            newStats.addStats(new TranslationStatistics(transUnitCountMap
                    .get(locale), locale));
            newStats.addStats(new TranslationStatistics(transUnitWordsMap
                    .get(locale), locale));

            if (newStats.getStats(locale, StatUnit.MESSAGE) != null
                    && newStats.getStats(locale, StatUnit.WORD) != null) {
                returnStats.put(new LocaleId(locale), newStats);
            }
        }

        return returnStats;
    }

    public HDocument getByGlobalId(GlobalDocumentId id) {
        return getByProjectIterationAndDocId(id.getProjectSlug(),
                id.getVersionSlug(), id.getDocId());
    }

    public HDocument getByProjectIterationAndDocId(final String projectSlug,
            final String iterationSlug, final String docId) {
        // TODO caching might be better with
        // getByDocIdAndIteration(ProjectIterationDAO.getBySlug(), docId)
        Session session = getSession();
        Query q =
                session.createQuery("from HDocument d "
                        + "where d.projectIteration.slug = :iterationSlug "
                        + "and d.projectIteration.project.slug = :projectSlug "
                        + "and d.docId = :docId " + "and d.obsolete = false");
        q.setParameter("iterationSlug", iterationSlug)
                .setParameter("projectSlug", projectSlug)
                .setParameter("docId", docId);
        q.setComment("DocumentDAO.getByProjectIterationAndDocId");
        q.setCacheable(true);
        final HDocument doc = (HDocument) q.uniqueResult();
        return doc;
    }

    public List<HDocument> getByProjectIterationAndDocIdList(
            final String projectSlug, final String iterationSlug,
            List<String> docIdList) {
        Session session = getSession();
        Query q =
                session.createQuery("from HDocument d "
                        + "where d.projectIteration.slug = :iterationSlug "
                        + "and d.projectIteration.project.slug = :projectSlug "
                        + "and d.docId in (:docIdList) "
                        + "and d.obsolete = false");
        q.setParameter("iterationSlug", iterationSlug)
                .setParameter("projectSlug", projectSlug)
                .setParameterList("docIdList", docIdList);
        q.setComment("DocumentDAO.getByProjectIterationAndDocIdList");
        q.setCacheable(true);
        List<HDocument> docs = q.list();
        return docs;
    }

    public List<HDocument> getAllByProjectIteration(final String projectSlug,
            final String iterationSlug) {
        return getByProjectIteration(projectSlug, iterationSlug, false);
    }

    public List<HDocument> getByProjectIteration(final String projectSlug,
            final String iterationSlug, boolean obsolete) {
        Session session = getSession();
        Query q =
                session.createQuery("from HDocument d "
                        + "where d.projectIteration.slug = :iterationSlug "
                        + "and d.projectIteration.project.slug = :projectSlug "
                        + "and d.obsolete = :obsolete "
                        + "order by d.path, d.name");
        q.setParameter("iterationSlug", iterationSlug)
                .setParameter("projectSlug", projectSlug)
                .setParameter("obsolete", obsolete);
        q.setComment("DocumentDAO.getByProjectIteration");
        // TODO q.setCacheable(true); ??
        return q.list();
    }

    public List<HDocument> findAllByVersionId(Long versionId, int offset,
            int maxResults) {
        Query q =
                getSession()
                        .createQuery(
                                "from HDocument doc where doc.obsolete=0 and doc.projectIteration.id = :versionId");
        q.setParameter("versionId", versionId);
        q.setFirstResult(offset);
        q.setMaxResults(maxResults);
        q.setCacheable(true).setComment("DocumentDAO.getDocByVersionId");
        return q.list();
    }

    public int getDocCountByVersion(String projectSlug, String versionSlug) {
        Long totalCount =
                (Long) getSession()
                        .createQuery(
                                "select count(doc) from HDocument doc "
                                        +
                                        "where doc.obsolete=0 and doc.projectIteration.slug = :versionSlug "
                                        +
                                        "and doc.projectIteration.project.slug = :projectSlug")
                        .setParameter("versionSlug", versionSlug)
                        .setParameter("projectSlug", projectSlug)
                        .setComment("DocumentDAO.getDocCountByVersion")
                        .setCacheable(true).uniqueResult();

        if (totalCount == null) {
            totalCount = 0L;
        }
        return totalCount.intValue();
    }

    /**
     * Calculates a translated document's hash.
     *
     * @param projectSlug
     *            Project identifier
     * @param iterationSlug
     *            Iteration identifier
     * @param docId
     *            Document identifier
     * @param locale
     *            Translated document's locale.
     * @return A Hash string (checksum) for a translated document.
     */
    @NativeQuery
    public String
            getTranslatedDocumentStateHash(final String projectSlug,
                    final String iterationSlug, final String docId,
                    final HLocale locale) {
        HDocument doc =
                getByProjectIterationAndDocId(projectSlug, iterationSlug, docId);
        if (doc == null) {
            return "";
        }
        // NB: This method uses a native SQL query tested on mysql and h2
        // databases.
        String sql =
                "select greatest(\n" + "  d.lastChanged,\n"
                        + "  max(ifnull(tft.lastChanged, {d '1753-01-01'})),\n"
                        + "  max(ifnull(c.lastChanged, {d '1753-01-01'})),\n"
                        + "  max(ifnull(poth.lastChanged, {d '1753-01-01'}))\n"
                        + ") as latest\n" + "from HDocument d\n"
                        + "  left outer join HTextFlow tf\n"
                        + "    on d.id = tf.document_id\n"
                        + "  left outer join HTextFlowTarget tft\n"
                        + "    on tft.tf_id = tf.id and tft.locale = :locale\n"
                        + "  left outer join HSimpleComment c\n"
                        + "    on c.id = tft.comment_id\n"
                        + "  left outer join HPoTargetHeader poth\n"
                        + "    on poth.document_id = d.id\n"
                        + "    and poth.targetLanguage = :locale\n"
                        + "where d.id = :doc\n" + "group by d.lastChanged";

        Query query =
                getSession().createSQLQuery(sql)
                        // ensure that mysql driver doesn't return byte[] :
                        .addScalar("latest", TimestampType.INSTANCE)
                        .setParameter("locale", locale)
                        .setParameter("doc", doc);
        Timestamp timestamp = (Timestamp) query.uniqueResult();
        return timestamp.toString();
    }

    /**
     * Do not use this method when adding a new raw document, instead use
     * {@link #addRawDocument(HDocument, HRawDocument)}
     *
     * @see AbstractDAOImpl#makePersistent(Object)
     */
    @Override
    public HDocument makePersistent(HDocument entity) {
        // TODO consider how to deal with old rawDocument.
        if (entity.getRawDocument() != null) {
            getSession().saveOrUpdate(entity.getRawDocument());
        }
        return super.makePersistent(entity);
    }

    /**
     * Add a raw document to a document, cleanly removing any existing raw
     * document associated with the document.
     *
     * @param doc
     * @param rawDoc
     * @return
     */
    public HRawDocument addRawDocument(HDocument doc, HRawDocument rawDoc) {
        HRawDocument oldRawDoc = doc.getRawDocument();

        if (oldRawDoc != null && !oldRawDoc.equals(rawDoc)) {
            getSession().delete(oldRawDoc);
        }

        if (rawDoc != null) {
            getSession().saveOrUpdate(rawDoc);
        }

        doc.setRawDocument(rawDoc);
        makePersistent(doc);
        return rawDoc;
    }

    public Optional<String> getAdapterParams(String projectSlug,
            String iterationSlug, String docId) {
        HDocument doc =
                getByProjectIterationAndDocId(projectSlug, iterationSlug, docId);
        if (doc != null) {
            HRawDocument rawDoc = doc.getRawDocument();
            if (rawDoc != null) {
                return Optional.fromNullable(rawDoc.getAdapterParameters());
            }
        }
        return Optional.<String> absent();
    }

    public List<HDocument> getDocumentsByIds(List<Long> docIds) {
        StringBuilder query = new StringBuilder();
        query.append("from HDocument doc where doc.id in (:docIds)");

        Query q = getSession().createQuery(query.toString());
        q.setParameterList("docIds", docIds);
        q.setCacheable(true);
        q.setComment("DocumentDAO.getDocumentsByIds");

        List<HDocument> docs = q.list();

        return docs;
    }

    public LobHelper getLobHelper() {
        return getSession().getLobHelper();
    }
}
TOP

Related Classes of org.zanata.dao.DocumentDAO

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.