Package org.zanata.search

Source Code of org.zanata.search.FilterConstraintToQuery

package org.zanata.search;

import java.util.Collection;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.criterion.MatchMode;
import org.joda.time.DateTime;
import org.zanata.model.HLocale;
import org.zanata.util.HqlCriterion;
import org.zanata.util.QueryBuilder;
import org.zanata.webtrans.shared.model.DocumentId;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import lombok.AccessLevel;
import lombok.Setter;

import static org.zanata.search.FilterConstraintToQuery.Parameters.*;
import static org.zanata.util.HqlCriterion.eq;
import static org.zanata.util.HqlCriterion.escapeWildcard;
import static org.zanata.util.HqlCriterion.ilike;
import static org.zanata.util.HqlCriterion.match;
import static org.zanata.util.QueryBuilder.and;

/**
* @author Patrick Huang <a
*         href="mailto:pahuang@redhat.com">pahuang@redhat.com</a>
*/
public class FilterConstraintToQuery {
    private final FilterConstraints constraints;
    private final boolean hasSearch;
    private String searchString;
    private DocumentId documentId;
    private Collection<Long> documentIds;

    @Setter(AccessLevel.PACKAGE)
    private ContentCriterion contentCriterion = new ContentCriterion();

    private FilterConstraintToQuery(FilterConstraints constraints,
            DocumentId documentId) {
        this(constraints);
        this.documentId = documentId;
    }

    public FilterConstraintToQuery(FilterConstraints constraints,
            Collection<Long> documentIds) {
        this(constraints);
        this.documentIds = documentIds;
    }

    private FilterConstraintToQuery(FilterConstraints constraints) {
        this.constraints = constraints;
        hasSearch = !Strings.isNullOrEmpty(constraints.getSearchString());
        if (hasSearch) {
            String term =
                    constraints.isCaseSensitive() ? constraints
                            .getSearchString() : constraints.getSearchString()
                            .toLowerCase();
            term = escapeWildcard(term);
            searchString = match(term, MatchMode.ANYWHERE);
        }
        contentCriterion = new ContentCriterion()
                .withCaseSensitive(constraints.isCaseSensitive());
    }

    public static FilterConstraintToQuery filterInSingleDocument(
            FilterConstraints constraints, DocumentId documentId) {
        Preconditions.checkNotNull(documentId);
        return new FilterConstraintToQuery(constraints, documentId);
    }

    public static FilterConstraintToQuery filterInMultipleDocuments(
            FilterConstraints constraints, Collection<Long> documentIds) {
        Preconditions.checkNotNull(documentIds);
        Preconditions.checkState(!documentIds.isEmpty());
        return new FilterConstraintToQuery(constraints, documentIds);
    }

    /**
     * This builds a query for constructing TransUnit in editor.
     * Executing the query will returns a list of HTextFlow objects.
     *
     * @return the HQL query
     */
    public String toEntityQuery() {
        String docIdCondition;
        if (documentId != null) {
            docIdCondition =
                    eq("tf.document.id", Parameters.DocumentId.placeHolder());
        } else {
            docIdCondition =
                    "tf.document.id in (" + DocumentIdList.placeHolder() + ")";
        }
        return buildQuery("distinct tf", docIdCondition);
    }

    private String buildQuery(String selectStatement, String docIdCondition) {

        String obsoleteCondition = eq("tf.obsolete", "0");
        String searchCondition = buildSearchCondition();
        String stateCondition = buildStateCondition();
        String otherSourceCondition = buildSourceConditionsOtherThanSearch();
        String otherTargetCondition = buildTargetConditionsOtherThanSearch();

        QueryBuilder query =
                QueryBuilder
                        .select(selectStatement)
                        .from("HTextFlow tf")
                        .leftJoin("tf.targets tfts")
                        .with(eq("tfts.index", Locale.placeHolder()))
                        .where(and(obsoleteCondition, docIdCondition,
                                searchCondition, stateCondition,
                                otherSourceCondition, otherTargetCondition))
                        .orderBy("tf.pos");
        return query.toQueryString();
    }

    /**
     * This builds a query for editor modal navigation. It only select text flow
     * id and text flow target content state (text flow pos is also in select
     * but just for ordering).
     *
     * @return the HQL query
     */
    public String toModalNavigationQuery() {
        String docIdCondition =
                eq("tf.document.id", Parameters.DocumentId.placeHolder());
        return buildQuery(
                "distinct tf.id as id, (case when tfts is null then 0 else tfts.state end) as state, tf.pos as pos, tf.resId as resId",
                docIdCondition);
    }

    protected String buildSearchCondition() {
        if (!hasSearch) {
            return null;
        }
        String searchInSourceCondition = null;
        if (constraints.isSearchInSource()) {
            searchInSourceCondition =
                    contentCriterion.withEntityAlias("tf")
                            .contentsCriterionAsString();
        }

        String searchInTargetCondition = null;
        if (constraints.isSearchInTarget()) {
            List<String> targetConjunction = Lists.newArrayList();
            targetConjunction.add(contentCriterion.contentsCriterionAsString());
            targetConjunction.add(eq("textFlow", "tf"));
            targetConjunction.add(eq("locale", Locale.placeHolder()));

            searchInTargetCondition =
                    QueryBuilder.exists().from("HTextFlowTarget")
                            .where(QueryBuilder.and(targetConjunction))
                            .toQueryString();
        }
        return QueryBuilder
                .or(searchInSourceCondition, searchInTargetCondition);
    }

    protected String buildSourceConditionsOtherThanSearch() {
        List<String> sourceConjunction = Lists.newArrayList();
        addToJunctionIfNotNull(sourceConjunction,
                buildSourceCommentCondition(constraints.getSourceComment()));
        addToJunctionIfNotNull(sourceConjunction, buildMsgContextCondition());
        addToJunctionIfNotNull(sourceConjunction, buildResourceIdCondition());
        if (sourceConjunction.isEmpty()) {
            return null;
        }
        return QueryBuilder.and(sourceConjunction);
    }

    protected String buildTargetConditionsOtherThanSearch() {
        List<String> targetConjunction = Lists.newArrayList();
        addToJunctionIfNotNull(targetConjunction,
                buildLastModifiedByCondition());
        addToJunctionIfNotNull(targetConjunction,
                buildTargetCommentCondition(constraints.getTransComment()));
        addToJunctionIfNotNull(targetConjunction,
                buildLastModifiedDateCondition());
        if (targetConjunction.isEmpty()) {
            return null;
        }
        targetConjunction.add(eq("textFlow", "tf"));
        targetConjunction.add(eq("locale", Locale.placeHolder()));

        return QueryBuilder.exists().from("HTextFlowTarget")
                .where(and(targetConjunction)).toQueryString();
    }

    private static boolean addToJunctionIfNotNull(List<String> junction,
            String criterion) {
        if (criterion != null) {
            junction.add(criterion);
            return true;
        }
        return false;
    }

    private String buildResourceIdCondition() {
        if (Strings.isNullOrEmpty(constraints.getResId())) {
            return null;
        }
        return eq("resId", ResId.placeHolder());
    }

    private String buildMsgContextCondition() {
        if (Strings.isNullOrEmpty(constraints.getMsgContext())) {
            return null;
        }
        return ilike("tf.potEntryData.context", MsgContext.placeHolder());
    }

    private String buildSourceCommentCondition(String commentToSearch) {
        if (Strings.isNullOrEmpty(commentToSearch)) {
            return null;
        }
        return ilike("tf.comment.comment", SourceComment.placeHolder());
    }

    private String buildTargetCommentCondition(String transComment) {
        if (Strings.isNullOrEmpty(transComment)) {
            return null;
        }
        return ilike("comment.comment", TargetComment.placeHolder());
    }

    private String buildLastModifiedDateCondition() {
        DateTime changedBeforeTime = constraints.getChangedBefore();
        DateTime changedAfterTime = constraints.getChangedAfter();
        if (changedBeforeTime == null && changedAfterTime == null) {
            return null;
        }
        String changedAfter = null;
        String changedBefore = null;
        if (changedAfterTime != null) {
            changedAfter =
                    HqlCriterion.gt("lastChanged",
                            LastChangedAfter.placeHolder());
        }
        if (changedBeforeTime != null) {
            changedBefore =
                    HqlCriterion.lt("lastChanged",
                            LastChangedBefore.placeHolder());
        }
        return QueryBuilder.and(changedAfter, changedBefore);
    }

    protected String buildStateCondition() {
        if (constraints.getIncludedStates().hasAllStates()) {
            return null;
        }
        List<String> conjunction = Lists.newArrayList();
        conjunction.add(eq("textFlow", "tf"));
        conjunction.add(eq("locale", Locale.placeHolder()));
        String textFlowAndLocaleRestriction =
                and(eq("textFlow", "tf"), eq("locale", Locale.placeHolder()));

        String stateInListWhereClause =
                and(textFlowAndLocaleRestriction,
                        String.format("state in (%s)",
                                ContentStateList.placeHolder()));
        String stateInListCondition =
                QueryBuilder.exists().from("HTextFlowTarget")
                        .where(stateInListWhereClause).toQueryString();
        if (constraints.getIncludedStates().hasNew()) {
            String nullTargetCondition =
                    String.format("%s not in indices(tf.targets)",
                            Locale.placeHolder());
            if (hasSearch && constraints.isSearchInSource()) {

                nullTargetCondition =
                        and(nullTargetCondition,
                                contentCriterion.withEntityAlias("tf")
                                        .contentsCriterionAsString());
            }
            return QueryBuilder.or(stateInListCondition, nullTargetCondition);
        }
        return stateInListCondition;
    }

    protected String buildLastModifiedByCondition() {
        if (Strings.isNullOrEmpty(constraints.getLastModifiedByUser())) {
            return null;
        }
        return eq("lastModifiedBy.account.username",
                LastModifiedBy.placeHolder());
    }

    public Query setQueryParameters(Query textFlowQuery, HLocale hLocale) {
        if (documentId != null) {
            textFlowQuery.setParameter(Parameters.DocumentId.namedParam(),
                    documentId.getId());
        } else {
            textFlowQuery.setParameterList(DocumentIdList.namedParam(),
                    documentIds);
        }
        textFlowQuery.setParameter(Locale.namedParam(), hLocale.getId());
        if (hasSearch) {
            textFlowQuery.setParameter(Parameters.SearchString.namedParam(),
                    searchString);
        }
        if (!constraints.getIncludedStates().hasAllStates()) {
            textFlowQuery.setParameterList(ContentStateList.namedParam(),
                    constraints.getIncludedStates().asList());
        }
        addExactMatchParamIfPresent(textFlowQuery, constraints.getResId(),
                ResId);
        addWildcardSearchParamIfPresent(textFlowQuery,
                constraints.getMsgContext(), MsgContext);
        addWildcardSearchParamIfPresent(textFlowQuery,
                constraints.getSourceComment(), SourceComment);
        addWildcardSearchParamIfPresent(textFlowQuery,
                constraints.getTransComment(), TargetComment);
        addExactMatchParamIfPresent(textFlowQuery,
                constraints.getLastModifiedByUser(), LastModifiedBy);
        if (constraints.getChangedAfter() != null) {
            textFlowQuery.setParameter(LastChangedAfter.namedParam(),
                    constraints.getChangedAfter().toDate());
        }
        if (constraints.getChangedBefore() != null) {
            textFlowQuery.setParameter(LastChangedBefore.namedParam(),
                    constraints.getChangedBefore().toDate());
        }
        return textFlowQuery;
    }

    private static void addExactMatchParamIfPresent(Query textFlowQuery,
            String filterProperty, Parameters filterParam) {
        if (!Strings.isNullOrEmpty(filterProperty)) {
            textFlowQuery
                    .setParameter(filterParam.namedParam(), filterProperty);
        }
    }

    private static Query addWildcardSearchParamIfPresent(Query textFlowQuery,
            String filterProperty, Parameters filterParam) {
        if (!Strings.isNullOrEmpty(filterProperty)) {
            String escapedAndLowered =
                    HqlCriterion.escapeWildcard(filterProperty.toLowerCase());
            textFlowQuery.setParameter(filterParam.namedParam(),
                    HqlCriterion.match(escapedAndLowered, MatchMode.ANYWHERE));
        }
        return textFlowQuery;
    }

    enum Parameters {
        SearchString, ContentStateList, Locale, DocumentId, DocumentIdList,
        ResId, SourceComment, MsgContext, TargetComment, LastModifiedBy,
        LastChangedAfter, LastChangedBefore;

        public String placeHolder() {
            return ":" + name();
        }

        public String namedParam() {
            return name();
        }

    }
}
TOP

Related Classes of org.zanata.search.FilterConstraintToQuery

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.