<commit_before>/*
 * Copyright 2014 - 2019 Blazebit.
 * Copyright 2010-2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.blazebit.persistence.spring.data.base.query;

import com.blazebit.persistence.CriteriaBuilderFactory;
import com.blazebit.persistence.FullQueryBuilder;
import com.blazebit.persistence.OrderByBuilder;
import com.blazebit.persistence.PagedList;
import com.blazebit.persistence.PaginatedCriteriaBuilder;
import com.blazebit.persistence.criteria.BlazeCriteria;
import com.blazebit.persistence.criteria.BlazeCriteriaBuilder;
import com.blazebit.persistence.criteria.BlazeCriteriaQuery;
import com.blazebit.persistence.spring.data.base.EntityViewSortUtil;
import com.blazebit.persistence.spring.data.base.query.JpaParameters.JpaParameter;
import com.blazebit.persistence.spring.data.repository.EntityViewSettingProcessor;
import com.blazebit.persistence.view.EntityViewManager;
import com.blazebit.persistence.view.EntityViewSetting;
import com.blazebit.persistence.spring.data.repository.BlazeSpecification;

import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.provider.PersistenceProvider;
import org.springframework.data.jpa.repository.query.AbstractJpaQuery;
import org.springframework.data.jpa.repository.query.FixedJpaCountQueryCreator;
import org.springframework.data.jpa.repository.query.FixedJpaQueryCreator;
import org.springframework.data.jpa.repository.query.JpaQueryExecution;
import org.springframework.data.jpa.repository.query.PartTreeJpaQuery;
import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.Parameters;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.data.repository.query.parser.PartTree;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;

/**
 * Implementation is similar to {@link PartTreeJpaQuery} but was modified to work with entity views.
 *
 * About sorting
 * The implementation of both {@link AbstractPartTreeBlazePersistenceQuery} and {@link com.blazebit.persistence.spring.data.base.repository.AbstractEntityViewAwareRepository}
 * aims to support mixed sorting, i.e. sorting by entity view attributes and entity attributes at the same time.
 * To make this work we abstain from using the attribute sorter API of {@link EntityViewSetting} because it would not
 * allow us to add the entity attribute sorts. Instead, we add both entity view attribute and entity attribute sorters
 * uniformly via the core order API of {@link OrderByBuilder} *after* the entity view settings have been applied:
 *   - For entity view attribute sorts we resolve deterministic aliases from the order property that correspond to the
 *     select item aliases
 *   - For entity attribute sorts we just use the order property as is
 *
 * @author <NAME>
 * @author <NAME>
 * @since 1.2.0
 */
public abstract class AbstractPartTreeBlazePersistenceQuery extends AbstractJpaQuery {

    private static final Pattern QUERY_PATTERN = Pattern.compile("^(((find|read|get|query)(All|One))|streamAll)$");

    private final Class<?> domainClass;
    private final Class<?> entityViewClass;
    private final PartTree tree;
    private final JpaParameters parameters;

    private final AbstractPartTreeBlazePersistenceQuery.QueryPreparer query;
    private final CriteriaBuilderFactory cbf;
    private final EntityViewManager evm;

    public AbstractPartTreeBlazePersistenceQuery(EntityViewAwareJpaQueryMethod method, EntityManager em, PersistenceProvider persistenceProvider, CriteriaBuilderFactory cbf, EntityViewManager evm) {

        super(method, em);

        this.cbf = cbf;
        this.evm = evm;

        this.entityViewClass = method.getEntityViewClass();
        this.domainClass = method.getEntityInformation().getJavaType();

        this.parameters = method.getJpaParameters();
        String methodName = method.getName();
        boolean skipMethodNamePredicateMatching = QUERY_PATTERN.matcher(methodName).matches();
        String source = skipMethodNamePredicateMatching ? "" : methodName;
        this.tree = new PartTree(source, domainClass);

        boolean hasEntityViewSettingProcessorParameter = parameters.hasEntityViewSettingProcessorParameter();
        boolean hasSpecificationParameter = parameters.hasSpecificationParameter();
        boolean hasCriteriaBuilderProcessorParameter = parameters.hasBlazeSpecificationParameter();
        boolean recreateQueries = parameters.potentiallySortsDynamically() || entityViewClass != null
                || skipMethodNamePredicateMatching
                || hasEntityViewSettingProcessorParameter
                || hasSpecificationParameter
                || hasCriteriaBuilderProcessorParameter;
        this.query = isCountProjection(tree) ? new AbstractPartTreeBlazePersistenceQuery.CountQueryPreparer(persistenceProvider,
            recreateQueries) : new AbstractPartTreeBlazePersistenceQuery.QueryPreparer(persistenceProvider, recreateQueries);<commit_msg>Use the same Spring pattern to match predicates<commit_after>/*
 * Copyright 2014 - 2019 Blazebit.
 * Copyright 2010-2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.blazebit.persistence.spring.data.base.query;

import com.blazebit.persistence.CriteriaBuilderFactory;
import com.blazebit.persistence.FullQueryBuilder;
import com.blazebit.persistence.OrderByBuilder;
import com.blazebit.persistence.PagedList;
import com.blazebit.persistence.PaginatedCriteriaBuilder;
import com.blazebit.persistence.criteria.BlazeCriteria;
import com.blazebit.persistence.criteria.BlazeCriteriaBuilder;
import com.blazebit.persistence.criteria.BlazeCriteriaQuery;
import com.blazebit.persistence.spring.data.base.EntityViewSortUtil;
import com.blazebit.persistence.spring.data.base.query.JpaParameters.JpaParameter;
import com.blazebit.persistence.spring.data.repository.EntityViewSettingProcessor;
import com.blazebit.persistence.view.EntityViewManager;
import com.blazebit.persistence.view.EntityViewSetting;
import com.blazebit.persistence.spring.data.repository.BlazeSpecification;

import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.provider.PersistenceProvider;
import org.springframework.data.jpa.repository.query.AbstractJpaQuery;
import org.springframework.data.jpa.repository.query.FixedJpaCountQueryCreator;
import org.springframework.data.jpa.repository.query.FixedJpaQueryCreator;
import org.springframework.data.jpa.repository.query.JpaQueryExecution;
import org.springframework.data.jpa.repository.query.PartTreeJpaQuery;
import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.Parameters;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.data.repository.query.parser.PartTree;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;

/**
 * Implementation is similar to {@link PartTreeJpaQuery} but was modified to work with entity views.
 *
 * About sorting
 * The implementation of both {@link AbstractPartTreeBlazePersistenceQuery} and {@link com.blazebit.persistence.spring.data.base.repository.AbstractEntityViewAwareRepository}
 * aims to support mixed sorting, i.e. sorting by entity view attributes and entity attributes at the same time.
 * To make this work we abstain from using the attribute sorter API of {@link EntityViewSetting} because it would not
 * allow us to add the entity attribute sorts. Instead, we add both entity view attribute and entity attribute sorters
 * uniformly via the core order API of {@link OrderByBuilder} *after* the entity view settings have been applied:
 *   - For entity view attribute sorts we resolve deterministic aliases from the order property that correspond to the
 *     select item aliases
 *   - For entity attribute sorts we just use the order property as is
 *
 * @author <NAME>
 * @author <NAME>
 * @since 1.2.0
 */
public abstract class AbstractPartTreeBlazePersistenceQuery extends AbstractJpaQuery {

    private static final String QUERY_PATTERN = "find|read|get|query|stream";
    private static final String COUNT_PATTERN = "count";
    private static final String EXISTS_PATTERN = "exists";
    private static final String DELETE_PATTERN = "delete|remove";
    private static final Pattern PREFIX_TEMPLATE = Pattern.compile( //
                    "^(" + QUERY_PATTERN + "|" + COUNT_PATTERN + "|" + EXISTS_PATTERN + "|" + DELETE_PATTERN + ")((\\p{Lu}.*?))??By");

    private final Class<?> domainClass;
    private final Class<?> entityViewClass;
    private final PartTree tree;
    private final JpaParameters parameters;

    private final AbstractPartTreeBlazePersistenceQuery.QueryPreparer query;
    private final CriteriaBuilderFactory cbf;
    private final EntityViewManager evm;

    public AbstractPartTreeBlazePersistenceQuery(EntityViewAwareJpaQueryMethod method, EntityManager em, PersistenceProvider persistenceProvider, CriteriaBuilderFactory cbf, EntityViewManager evm) {

        super(method, em);

        this.cbf = cbf;
        this.evm = evm;

        this.entityViewClass = method.getEntityViewClass();
        this.domainClass = method.getEntityInformation().getJavaType();

        this.parameters = method.getJpaParameters();
        String methodName = method.getName();
        boolean skipMethodNamePredicateMatching = !PREFIX_TEMPLATE.matcher(methodName).find();
        String source = skipMethodNamePredicateMatching ? "" : methodName;
        this.tree = new PartTree(source, domainClass);

        boolean hasEntityViewSettingProcessorParameter = parameters.hasEntityViewSettingProcessorParameter();
        boolean hasSpecificationParameter = parameters.hasSpecificationParameter();
        boolean hasCriteriaBuilderProcessorParameter = parameters.hasBlazeSpecificationParameter();
        boolean recreateQueries = parameters.potentiallySortsDynamically() || entityViewClass != null
                || skipMethodNamePredicateMatching
                || hasEntityViewSettingProcessorParameter
                || hasSpecificationParameter
                || hasCriteriaBuilderProcessorParameter;
        this.query = isCountProjection(tree) ? new AbstractPartTreeBlazePersistenceQuery.CountQueryPreparer(persistenceProvider,
            recreateQueries) : new AbstractPartTreeBlazePersistenceQuery.QueryPreparer(persistenceProvider, recreateQueries);
{'fraction_non_alphanumeric': 0.07739438890680425, 'fraction_numerical': 0.003708481135117704, 'mean_word_length': 5.0541727672035135, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1226273', 'n_tokens_mistral': 3237, 'n_tokens_neox': 3188, 'n_words': 845}