/*
 * Copyright 2016 - 2021 Acosix GmbH
 *
 * 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 de.acosix.alfresco.utility.repo.batch;

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

import org.alfresco.repo.batch.BatchProcessWorkProvider;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.LimitBy;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.util.PropertyCheck;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;

/**
 * This class provides a generic work provider for batch operations that process generic {@link NodeRef NodeRefs} as units of work, querying
 * relevant work items with a one-off bulk, transactional metadata query.
 *
 * @author Axel Faust
 */
public class BulkQueryNodeBatchWorkProvider implements BatchProcessWorkProvider<NodeRef>, InitializingBean
{

    private static final Logger LOGGER = LoggerFactory.getLogger(BulkQueryNodeBatchWorkProvider.class);

    protected SearchService searchService;

    protected String language = SearchService.LANGUAGE_FTS_ALFRESCO;

    protected String query;

    protected volatile boolean queried = false;

    /**
     *
     * {@inheritDoc}
     */
    @Override
    public void afterPropertiesSet()
    {
        PropertyCheck.mandatory(this, "searchService", this.searchService);
        PropertyCheck.mandatory(this, "language", this.language);
        PropertyCheck.mandatory(this, "query", this.query);
    }

    /**
     * @param searchService
     *            the searchService to set
     */
    public void setSearchService(final SearchService searchService)
    {
        this.searchService = searchService;
    }

    /**
     * @param language
     *            the language to set
     */
    public void setLanguage(final String language)
    {
        this.language = language;
    }

    /**
     * @param query
     *            the query to set
     */
    public void setQuery(final String query)
    {
        this.query = query;
    }

    /**
     *
     * {@inheritDoc}
     */
    @Override
    public int getTotalEstimatedWorkSize()
    {
        // can't efficiently determine number of affected nodes without doing an actual (expensive) query
        return 0;
    }

    /**
     *
     * {@inheritDoc}
     */
    @Override
    public Collection<NodeRef> getNextWork()
    {
        final Collection<NodeRef> nextWork;

        if (this.queried)
        {
            nextWork = Collections.emptyList();
        }
        else
        {
            nextWork = AuthenticationUtil.runAsSystem(() -> {
                final SearchParameters sp = new SearchParameters();
                sp.addStore(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
                sp.setLanguage(this.language);
                sp.setQuery(this.query);
                sp.setMaxItems(Integer.MAX_VALUE);
                sp.setMaxPermissionChecks(Integer.MAX_VALUE);
                sp.setMaxPermissionCheckTimeMillis(Long.MAX_VALUE);
                sp.setLimit(Integer.MAX_VALUE);
                sp.setLimitBy(LimitBy.UNLIMITED);
                sp.setBulkFetchEnabled(false);

                final ResultSet results = this.searchService.query(sp);
                try
                {
                    final List<NodeRef> resultNodes = results.getNodeRefs();
                    LOGGER.debug("Loaded {} work items", resultNodes.size());
                    return resultNodes;
                }
                finally
                {
                    this.queried = true;
                    results.close();
                }
            });
        }

        return nextWork;
    }
}

@@ -1001,16 +1001,73 @@
 imitBy;%0A
+import org.alfresco.service.cmr.search.QueryConsistency;%0A
 import o
@@ -1108,16 +1108,16 @@
 ultSet;%0A
-
 import o
@@ -1982,16 +1982,66 @@
 query;%0A%0A
+    protected QueryConsistency queryConsistency;%0A%0A
     prot
@@ -2425,39 +2425,32 @@
 chService%0A     *
-       
      the searchS
@@ -2629,31 +2629,24 @@
 guage%0A     *
-       
      the lan
@@ -2798,23 +2798,16 @@
 y%0A     *
-       
      the
@@ -2906,32 +2906,258 @@
 = query;%0A    %7D%0A%0A
+    /**%0A     * @param queryConsistency%0A     *     the queryConsistency to set%0A     */%0A    public void setQueryConsistency(final QueryConsistency queryConsistency)%0A    %7B%0A        this.queryConsistency = queryConsistency;%0A    %7D%0A%0A
     /**%0A     *%0A 
@@ -3889,32 +3889,32 @@
 this.language);%0A
-
                 
@@ -3934,24 +3934,87 @@
 his.query);%0A
+                sp.setQueryConsistency(this.queryConsistency);%0A
             

Support query consistency parameter