/*
* Copyright 2015 herd contributors
*
* 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 org.finra.herd.service.impl;

import java.util.List;
import java.util.concurrent.Future;

import org.elasticsearch.client.AdminClient;
import org.elasticsearch.client.transport.TransportClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import org.finra.herd.dao.BusinessObjectDefinitionDao;
import org.finra.herd.dao.config.DaoSpringModuleConfig;
import org.finra.herd.model.api.xml.SearchIndexKey;
import org.finra.herd.model.jpa.BusinessObjectDefinitionEntity;
import org.finra.herd.model.jpa.SearchIndexStatusEntity;
import org.finra.herd.service.SearchIndexHelperService;
import org.finra.herd.service.functional.SearchFunctions;
import org.finra.herd.service.helper.BusinessObjectDefinitionHelper;
import org.finra.herd.service.helper.SearchIndexDaoHelper;

/**
 * An implementation of the helper service class for the search index service.
 */
@Service
@Transactional(value = DaoSpringModuleConfig.HERD_TRANSACTION_MANAGER_BEAN_NAME)
public class SearchIndexHelperServiceImpl implements SearchIndexHelperService
{
    public static final int BUSINESS_OBJECT_DEFINITIONS_CHUNK_SIZE = 100;

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

    @Autowired
    private BusinessObjectDefinitionDao businessObjectDefinitionDao;

    @Autowired
    private BusinessObjectDefinitionHelper businessObjectDefinitionHelper;

    @Autowired
    private SearchFunctions searchFunctions;

    @Autowired
    private SearchIndexDaoHelper searchIndexDaoHelper;

    @Autowired
    private TransportClient transportClient;

    @Override
    public AdminClient getAdminClient()
    {
        return transportClient.admin();
    }

    @Override
    @Async
    public Future<Void> indexAllBusinessObjectDefinitions(SearchIndexKey searchIndexKey, String documentType)
    {
        // Index all business object definitions defined in the system using pagination.
        int startPosition = 0;
        List<BusinessObjectDefinitionEntity> businessObjectDefinitionEntities;
        while ((businessObjectDefinitionEntities =
            businessObjectDefinitionDao.getAllBusinessObjectDefinitions(startPosition, BUSINESS_OBJECT_DEFINITIONS_CHUNK_SIZE)).size() > 0)
        {
            // Indexes selected business object definition entities.
            indexBusinessObjectDefinitions(searchIndexKey, documentType, businessObjectDefinitionEntities);

            // Increment the offset.
            startPosition = startPosition + BUSINESS_OBJECT_DEFINITIONS_CHUNK_SIZE;
        }

        // Return an AsyncResult so callers will know the future is "done". They can call "isDone" to know when this method has completed and they can call
        // "get" to see if any exceptions were thrown.
        return new AsyncResult<>(null);
    }

    /**
     * Performs a simple count validation on the specified search index.
     *
     * @param indexName the name of the index
     * @param documentType the document type
     * @param expectedIndexSize the expected index size
     *
     * @return true if index size matches the expected size, false otherwise
     */
    protected boolean validateSearchIndexSize(String indexName, String documentType, int expectedIndexSize)
    {
        final long indexSize = searchFunctions.getNumberOfTypesInIndexFunction().apply(indexName, documentType);

        boolean result = true;
        if (indexSize != expectedIndexSize)
        {
            LOGGER.error("Index validation failed, expected index size {}, does not equal actual index size {}.", expectedIndexSize, indexSize);
            result = false;
        }

        return result;
    }

    /**
     * Indexes business object definitions.
     *
     * @param searchIndexKey the key of the search index
     * @param documentType the document type
     * @param businessObjectDefinitionEntities the list of business object definition entities
     */
    private void indexBusinessObjectDefinitions(SearchIndexKey searchIndexKey, String documentType,
        List<BusinessObjectDefinitionEntity> businessObjectDefinitionEntities)
    {
        // Index business object definitions.
        businessObjectDefinitionHelper
            .executeFunctionForBusinessObjectDefinitionEntities(searchIndexKey.getSearchIndexName(), documentType, businessObjectDefinitionEntities,
                searchFunctions.getIndexFunction());

        // Perform a simple count validation, index size should equal entity list size.
        validateSearchIndexSize(searchIndexKey.getSearchIndexName(), documentType, businessObjectDefinitionEntities.size());

        // Update search index status to READY.
        searchIndexDaoHelper.updateSearchIndexStatus(searchIndexKey, SearchIndexStatusEntity.SearchIndexStatuses.READY.name());
    }
}

@@ -2832,16 +2832,73 @@
 on = 0;%0A
+        int processedBusinessObjectDefinitionsCount = 0;%0A
         
@@ -3414,25 +3414,10 @@
 ion 
-= startPosition 
 +
+=
  BUS
@@ -3453,25 +3453,427 @@
 K_SIZE;%0A
-        %7D
+%0A            // Increment the total count of processed business object definition entities.%0A            processedBusinessObjectDefinitionsCount += businessObjectDefinitionEntities.size();%0A        %7D%0A%0A        // Perform a simple count validation, index size should equal entity list size.%0A        validateSearchIndexSize(searchIndexKey.getSearchIndexName(), documentType, processedBusinessObjectDefinitionsCount);
 %0A%0A      
@@ -5719,222 +5719,8 @@
 );%0A%0A
-        // Perform a simple count validation, index size should equal entity list size.%0A        validateSearchIndexSize(searchIndexKey.getSearchIndexName(), documentType, businessObjectDefinitionEntities.size());%0A%0A
     

Manage BDef indexing and view index status