# PartTreeStalactiteQuery.java

    package org.codefilarete.stalactite.spring.repository.query.domain;

    import java.util.List;
    import java.util.function.LongSupplier;

    import org.codefilarete.stalactite.engine.runtime.AdvancedEntityPersister;
    import org.codefilarete.stalactite.spring.repository.query.execution.AbstractQueryExecutor;
    import org.codefilarete.stalactite.spring.repository.query.execution.AbstractRepositoryQuery;
    import org.codefilarete.stalactite.spring.repository.query.StalactiteQueryMethod;
    import org.codefilarete.stalactite.spring.repository.query.execution.StalactiteQueryMethodInvocationParameters;
    import org.codefilarete.stalactite.spring.repository.query.projection.PartTreeStalactiteCountProjection;
    import org.springframework.data.repository.query.QueryMethod;
    import org.springframework.data.repository.query.RepositoryQuery;
    import org.springframework.data.repository.query.parser.PartTree;

    /**
     * {@link RepositoryQuery} for Stalactite. Inspired by {@link org.springframework.data.jpa.repository.query.PartTreeJpaQuery}.
     * The parsing of the {@link QueryMethod} is made by Spring {@link PartTree}, hence this class only iterates over parts
     * to create a Stalactite query.
     *
     * @param <C> entity type
     * @author Guillaume Mary
     */
    public class PartTreeStalactiteQuery<C, R> extends AbstractRepositoryQuery<C, R> {

    	private final AdvancedEntityPersister<C, ?> entityPersister;
    	private final PartTree partTree;
    	private final PartTreeStalactiteCountProjection<C> countQuery;

    	public PartTreeStalactiteQuery(StalactiteQueryMethod method,
    								   AdvancedEntityPersister<C, ?> entityPersister,
    								   PartTree partTree) {
    		super(method);
    		this.entityPersister = entityPersister;
    		this.partTree = partTree;
    		this.countQuery = new PartTreeStalactiteCountProjection<>(method, entityPersister, partTree);
    	}

    	@Override
    	protected AbstractQueryExecutor<List<Object>, Object> buildQueryExecutor(StalactiteQueryMethodInvocationParameters invocationParameters) {
    		return (AbstractQueryExecutor) new DomainEntityQueryExecutor<>(method, entityPersister, partTree);
    	}

    	@Override
    	protected LongSupplier buildCountSupplier(StalactiteQueryMethodInvocationParameters accessor) {
    		return () -> countQuery.execute(accessor.getValues());
    	}

    	@Override
    	public StalactiteQueryMethod getQueryMethod() {
    		return method;
    	}
    }