All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.finra.herd.service.impl.BusinessObjectDefinitionServiceImpl Maven / Gradle / Ivy

Go to download

This project contains the business service code. This is a classic service tier where business logic is defined along with it's associated transaction management configuration.

There is a newer version: 0.160.0
Show newest version
/*
* 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 static org.finra.herd.model.dto.SearchIndexUpdateDto.SEARCH_INDEX_UPDATE_TYPE_CREATE;
import static org.finra.herd.model.dto.SearchIndexUpdateDto.SEARCH_INDEX_UPDATE_TYPE_DELETE;
import static org.finra.herd.model.dto.SearchIndexUpdateDto.SEARCH_INDEX_UPDATE_TYPE_UPDATE;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import com.google.common.collect.ImmutableSet;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
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.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import org.finra.herd.core.HerdDateUtils;
import org.finra.herd.core.HerdStringUtils;
import org.finra.herd.core.helper.ConfigurationHelper;
import org.finra.herd.dao.BusinessObjectDefinitionDao;
import org.finra.herd.dao.IndexFunctionsDao;
import org.finra.herd.dao.config.DaoSpringModuleConfig;
import org.finra.herd.dao.helper.TagDaoHelper;
import org.finra.herd.model.annotation.NamespacePermission;
import org.finra.herd.model.api.xml.Attribute;
import org.finra.herd.model.api.xml.BusinessObjectDefinition;
import org.finra.herd.model.api.xml.BusinessObjectDefinitionChangeEvent;
import org.finra.herd.model.api.xml.BusinessObjectDefinitionCreateRequest;
import org.finra.herd.model.api.xml.BusinessObjectDefinitionDescriptiveInformationUpdateRequest;
import org.finra.herd.model.api.xml.BusinessObjectDefinitionKey;
import org.finra.herd.model.api.xml.BusinessObjectDefinitionKeys;
import org.finra.herd.model.api.xml.BusinessObjectDefinitionSearchFilter;
import org.finra.herd.model.api.xml.BusinessObjectDefinitionSearchKey;
import org.finra.herd.model.api.xml.BusinessObjectDefinitionSearchRequest;
import org.finra.herd.model.api.xml.BusinessObjectDefinitionSearchResponse;
import org.finra.herd.model.api.xml.BusinessObjectDefinitionUpdateRequest;
import org.finra.herd.model.api.xml.BusinessObjectFormatKey;
import org.finra.herd.model.api.xml.DescriptiveBusinessObjectFormat;
import org.finra.herd.model.api.xml.DescriptiveBusinessObjectFormatUpdateRequest;
import org.finra.herd.model.api.xml.NamespacePermissionEnum;
import org.finra.herd.model.api.xml.SampleDataFile;
import org.finra.herd.model.dto.BusinessObjectDefinitionSampleFileUpdateDto;
import org.finra.herd.model.dto.ConfigurationValue;
import org.finra.herd.model.dto.SearchIndexUpdateDto;
import org.finra.herd.model.jpa.BusinessObjectDefinitionAttributeEntity;
import org.finra.herd.model.jpa.BusinessObjectDefinitionEntity;
import org.finra.herd.model.jpa.BusinessObjectDefinitionSampleDataFileEntity;
import org.finra.herd.model.jpa.BusinessObjectFormatEntity;
import org.finra.herd.model.jpa.StorageEntity;
import org.finra.herd.model.jpa.TagEntity;
import org.finra.herd.service.BusinessObjectDefinitionService;
import org.finra.herd.service.FacetFieldValidationService;
import org.finra.herd.service.SearchableService;
import org.finra.herd.service.helper.AlternateKeyHelper;
import org.finra.herd.service.helper.AttributeHelper;
import org.finra.herd.service.helper.BusinessObjectDefinitionDaoHelper;
import org.finra.herd.service.helper.BusinessObjectDefinitionHelper;
import org.finra.herd.service.helper.BusinessObjectFormatDaoHelper;
import org.finra.herd.service.helper.SearchIndexUpdateHelper;
import org.finra.herd.service.helper.StorageDaoHelper;
import org.finra.herd.service.helper.TagHelper;

/**
 * The business object definition service implementation.
 */
@Service
@Transactional(value = DaoSpringModuleConfig.HERD_TRANSACTION_MANAGER_BEAN_NAME)
// TODO: Refactor the service implementation and remove the PMD suppress warning statement below.
@SuppressWarnings("PMD.TooManyMethods")
public class BusinessObjectDefinitionServiceImpl implements BusinessObjectDefinitionService, SearchableService, FacetFieldValidationService
{
    private static final Logger LOGGER = LoggerFactory.getLogger(BusinessObjectDefinitionServiceImpl.class);

    /**
     * The size of the chunks to use when updating search index documents based on a list of ids.
     */
    public static final int UPDATE_SEARCH_INDEX_DOCUMENT_CHUNK_SIZE = 100;

    @Autowired
    private AlternateKeyHelper alternateKeyHelper;

    @Autowired
    private AttributeHelper attributeHelper;

    @Autowired
    private BusinessObjectDefinitionDao businessObjectDefinitionDao;

    @Autowired
    private BusinessObjectDefinitionDaoHelper businessObjectDefinitionDaoHelper;

    @Autowired
    private BusinessObjectDefinitionHelper businessObjectDefinitionHelper;

    @Autowired
    private BusinessObjectFormatDaoHelper businessObjectFormatDaoHelper;

    @Autowired
    private ConfigurationHelper configurationHelper;

    @Autowired
    private IndexFunctionsDao indexFunctionsDao;

    @Autowired
    private TagHelper tagHelper;

    @Autowired
    private TagDaoHelper tagDaoHelper;

    @Autowired
    private StorageDaoHelper storageDaoHelper;

    @Autowired
    private SearchIndexUpdateHelper searchIndexUpdateHelper;

    // Constant to hold the data provider name option for the business object definition search
    private static final String DATA_PROVIDER_NAME_FIELD = "dataprovidername";

    // Constant to hold the short description option for the business object definition search
    private static final String SHORT_DESCRIPTION_FIELD = "shortdescription";

    // Constant to hold the display name option for the business object definition search
    private static final String DISPLAY_NAME_FIELD = "displayname";

    private static final String TAG_FACET_FIELD = "tag";

    /**
     * {@inheritDoc}
     * 

* This implementation starts a new transaction. */ @NamespacePermission(fields = "#request.namespace", permissions = NamespacePermissionEnum.WRITE) @Override @Transactional(propagation = Propagation.REQUIRES_NEW) public BusinessObjectDefinition createBusinessObjectDefinition(BusinessObjectDefinitionCreateRequest request) { return createBusinessObjectDefinitionImpl(request); } /** * Creates a new business object definition. * * @param request the business object definition create request * * @return the created business object definition */ protected BusinessObjectDefinition createBusinessObjectDefinitionImpl(BusinessObjectDefinitionCreateRequest request) { BusinessObjectDefinitionEntity businessObjectDefinitionEntity = businessObjectDefinitionDaoHelper.createBusinessObjectDefinitionEntity(request); // Notify the search index that a business object definition must be created. LOGGER.info("Create the business object definition in the search index associated with the business object definition being created." + " businessObjectDefinitionId=\"{}\", searchIndexUpdateType=\"{}\"", businessObjectDefinitionEntity.getId(), SEARCH_INDEX_UPDATE_TYPE_CREATE); searchIndexUpdateHelper.modifyBusinessObjectDefinitionInSearchIndex(businessObjectDefinitionEntity, SEARCH_INDEX_UPDATE_TYPE_CREATE); // Create and return the business object definition object from the persisted entity. return createBusinessObjectDefinitionFromEntity(businessObjectDefinitionEntity, false); } @Override public boolean indexSizeCheckValidationBusinessObjectDefinitions(String indexName) { final String documentType = configurationHelper.getProperty(ConfigurationValue.ELASTICSEARCH_BDEF_DOCUMENT_TYPE, String.class); // Simple count validation, index size should equal entity list size final long indexSize = indexFunctionsDao.getNumberOfTypesInIndex(indexName, documentType); final long businessObjectDefinitionDatabaseTableSize = businessObjectDefinitionDao.getCountOfAllBusinessObjectDefinitions(); if (businessObjectDefinitionDatabaseTableSize != indexSize) { LOGGER.error("Index validation failed, business object definition database table size {}, does not equal index size {}.", businessObjectDefinitionDatabaseTableSize, indexSize); } return businessObjectDefinitionDatabaseTableSize == indexSize; } @Override public boolean indexSpotCheckPercentageValidationBusinessObjectDefinitions(String indexName) { final Double spotCheckPercentage = configurationHelper.getProperty(ConfigurationValue.ELASTICSEARCH_BDEF_SPOT_CHECK_PERCENTAGE, Double.class); // Get a list of all business object definitions final List businessObjectDefinitionEntityList = Collections.unmodifiableList(businessObjectDefinitionDao.getPercentageOfAllBusinessObjectDefinitions(spotCheckPercentage)); return indexValidateBusinessObjectDefinitionsList(businessObjectDefinitionEntityList, indexName); } @Override public boolean indexSpotCheckMostRecentValidationBusinessObjectDefinitions(String indexName) { final Integer spotCheckMostRecentNumber = configurationHelper.getProperty(ConfigurationValue.ELASTICSEARCH_BDEF_SPOT_CHECK_MOST_RECENT_NUMBER, Integer.class); // Get a list of all business object definitions final List businessObjectDefinitionEntityList = Collections.unmodifiableList(businessObjectDefinitionDao.getMostRecentBusinessObjectDefinitions(spotCheckMostRecentNumber)); return indexValidateBusinessObjectDefinitionsList(businessObjectDefinitionEntityList, indexName); } @Override @Async public Future indexValidateAllBusinessObjectDefinitions(String indexName) { final String documentType = configurationHelper.getProperty(ConfigurationValue.ELASTICSEARCH_BDEF_DOCUMENT_TYPE, String.class); // Get a list of all business object definitions final List businessObjectDefinitionEntityList = Collections.unmodifiableList(businessObjectDefinitionDao.getAllBusinessObjectDefinitions()); // Remove any index documents that are not in the database removeAnyIndexDocumentsThatAreNotInBusinessObjectsDefinitionsList(indexName, documentType, businessObjectDefinitionEntityList); // Validate all Business Object Definitions businessObjectDefinitionHelper.executeFunctionForBusinessObjectDefinitionEntities(indexName, documentType, businessObjectDefinitionEntityList, indexFunctionsDao::validateDocumentIndex); // 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); } /** * Method to remove business object definitions in the index that don't exist in the database * * @param indexName the name of the index * @param documentType the document type * @param businessObjectDefinitionEntityList list of business object definitions in the database */ private void removeAnyIndexDocumentsThatAreNotInBusinessObjectsDefinitionsList(final String indexName, final String documentType, List businessObjectDefinitionEntityList) { // Get a list of business object definition ids from the list of business object definition entities in the database List databaseBusinessObjectDefinitionIdList = new ArrayList<>(); businessObjectDefinitionEntityList .forEach(businessObjectDefinitionEntity -> databaseBusinessObjectDefinitionIdList.add(businessObjectDefinitionEntity.getId().toString())); // Get a list of business object definition ids in the search index List indexDocumentBusinessObjectDefinitionIdList = indexFunctionsDao.getIdsInIndex(indexName, documentType); // Remove the database ids from the index ids indexDocumentBusinessObjectDefinitionIdList.removeAll(databaseBusinessObjectDefinitionIdList); // If there are any ids left in the index list they need to be removed indexDocumentBusinessObjectDefinitionIdList.forEach(id -> indexFunctionsDao.deleteDocumentById(indexName, documentType, id)); } /** * A helper method that will validate a list of business object definitions * * @param businessObjectDefinitionEntityList the list of business object definitions that will be validated * * @return true all of the business object definitions are valid in the index */ private boolean indexValidateBusinessObjectDefinitionsList(final List businessObjectDefinitionEntityList, String indexName) { final String documentType = configurationHelper.getProperty(ConfigurationValue.ELASTICSEARCH_BDEF_DOCUMENT_TYPE, String.class); Predicate validInIndexPredicate = businessObjectDefinitionEntity -> { // Fetch Join with .size() businessObjectDefinitionEntity.getAttributes().size(); businessObjectDefinitionEntity.getBusinessObjectDefinitionTags().size(); businessObjectDefinitionEntity.getBusinessObjectFormats().size(); businessObjectDefinitionEntity.getColumns().size(); businessObjectDefinitionEntity.getSampleDataFiles().size(); // Convert the business object definition entity to a JSON string final String jsonString = businessObjectDefinitionHelper.safeObjectMapperWriteValueAsString(businessObjectDefinitionEntity); return indexFunctionsDao.isValidDocumentIndex(indexName, documentType, businessObjectDefinitionEntity.getId().toString(), jsonString); }; boolean isValid = true; for (BusinessObjectDefinitionEntity businessObjectDefinitionEntity : businessObjectDefinitionEntityList) { if (!validInIndexPredicate.test(businessObjectDefinitionEntity)) { isValid = false; } } return isValid; } /** * {@inheritDoc} *

* This implementation starts a new transaction. */ @NamespacePermission(fields = "#businessObjectDefinitionKey.namespace", permissions = NamespacePermissionEnum.WRITE) @Override @Transactional(propagation = Propagation.REQUIRES_NEW) public BusinessObjectDefinition updateBusinessObjectDefinition(BusinessObjectDefinitionKey businessObjectDefinitionKey, BusinessObjectDefinitionUpdateRequest request) { return updateBusinessObjectDefinitionImpl(businessObjectDefinitionKey, request); } /** * Updates a business object definition. * * @param businessObjectDefinitionKey the business object definition key * @param request the business object definition update request * * @return the updated business object definition */ protected BusinessObjectDefinition updateBusinessObjectDefinitionImpl(BusinessObjectDefinitionKey businessObjectDefinitionKey, BusinessObjectDefinitionUpdateRequest request) { // Perform validation and trim. businessObjectDefinitionHelper.validateBusinessObjectDefinitionKey(businessObjectDefinitionKey); validateBusinessObjectDefinitionUpdateRequest(request); // Retrieve and ensure that a business object definition already exists with the specified key. BusinessObjectDefinitionEntity businessObjectDefinitionEntity = businessObjectDefinitionDaoHelper.getBusinessObjectDefinitionEntity(businessObjectDefinitionKey); // Update and persist the entity. updateBusinessObjectDefinitionEntity(businessObjectDefinitionEntity, request); // Notify the search index that a business object definition must be updated. LOGGER.info("Modify the business object definition in the search index associated with the business object definition being updated." + " businessObjectDefinitionId=\"{}\", searchIndexUpdateType=\"{}\"", businessObjectDefinitionEntity.getId(), SEARCH_INDEX_UPDATE_TYPE_UPDATE); searchIndexUpdateHelper.modifyBusinessObjectDefinitionInSearchIndex(businessObjectDefinitionEntity, SEARCH_INDEX_UPDATE_TYPE_UPDATE); // Create and return the business object definition object from the persisted entity. return createBusinessObjectDefinitionFromEntity(businessObjectDefinitionEntity, false); } /** * {@inheritDoc} *

* This implementation starts a new transaction. */ @NamespacePermission(fields = "#businessObjectDefinitionKey.namespace", permissions = {NamespacePermissionEnum.WRITE_DESCRIPTIVE_CONTENT, NamespacePermissionEnum.WRITE}) @Override @Transactional(propagation = Propagation.REQUIRES_NEW) public BusinessObjectDefinition updateBusinessObjectDefinitionDescriptiveInformation(BusinessObjectDefinitionKey businessObjectDefinitionKey, BusinessObjectDefinitionDescriptiveInformationUpdateRequest request) { return updateBusinessObjectDefinitionDescriptiveInformationImpl(businessObjectDefinitionKey, request); } /** * Updates a business object definition descriptive information. * * @param businessObjectDefinitionKey the business object definition key * @param request the business object definition descriptive information update request * * @return the updated business object definition */ protected BusinessObjectDefinition updateBusinessObjectDefinitionDescriptiveInformationImpl(BusinessObjectDefinitionKey businessObjectDefinitionKey, BusinessObjectDefinitionDescriptiveInformationUpdateRequest request) { // Perform validation and trim. businessObjectDefinitionHelper.validateBusinessObjectDefinitionKey(businessObjectDefinitionKey); validateBusinessObjectDefinitionDescriptiveInformationUpdateRequest(request); // Retrieve and ensure that a business object definition already exists with the specified key. BusinessObjectDefinitionEntity businessObjectDefinitionEntity = businessObjectDefinitionDaoHelper.getBusinessObjectDefinitionEntity(businessObjectDefinitionKey); BusinessObjectFormatEntity businessObjectFormatEntity = null; DescriptiveBusinessObjectFormatUpdateRequest descriptiveFormat = request.getDescriptiveBusinessObjectFormat(); if (descriptiveFormat != null) { BusinessObjectFormatKey businessObjectFormatKey = new BusinessObjectFormatKey(); businessObjectFormatKey.setBusinessObjectDefinitionName(businessObjectDefinitionEntity.getName()); businessObjectFormatKey.setNamespace(businessObjectDefinitionEntity.getNamespace().getCode()); businessObjectFormatKey.setBusinessObjectFormatFileType(descriptiveFormat.getBusinessObjectFormatFileType()); businessObjectFormatKey.setBusinessObjectFormatUsage(descriptiveFormat.getBusinessObjectFormatUsage()); businessObjectFormatEntity = businessObjectFormatDaoHelper.getBusinessObjectFormatEntity(businessObjectFormatKey); } businessObjectDefinitionEntity.setDescriptiveBusinessObjectFormat(businessObjectFormatEntity); // Update and persist the entity. updateBusinessObjectDefinitionEntityDescriptiveInformation(businessObjectDefinitionEntity, request); // Notify the search index that a business object definition must be updated. LOGGER.info("Modify the business object definition in the search index associated with the business object definition being updated." + " businessObjectDefinitionId=\"{}\", searchIndexUpdateType=\"{}\"", businessObjectDefinitionEntity.getId(), SEARCH_INDEX_UPDATE_TYPE_UPDATE); searchIndexUpdateHelper.modifyBusinessObjectDefinitionInSearchIndex(businessObjectDefinitionEntity, SEARCH_INDEX_UPDATE_TYPE_UPDATE); // Create and return the business object definition object from the persisted entity. return createBusinessObjectDefinitionFromEntity(businessObjectDefinitionEntity, false); } /** * {@inheritDoc} *

* This implementation starts a new transaction. */ @Override @Transactional(propagation = Propagation.REQUIRES_NEW) public BusinessObjectDefinition getBusinessObjectDefinition(BusinessObjectDefinitionKey businessObjectDefinitionKey, Boolean includeBusinessObjectDefinitionUpdateHistory) { return getBusinessObjectDefinitionImpl(businessObjectDefinitionKey, includeBusinessObjectDefinitionUpdateHistory); } /** * Gets a business object definition for the specified key. * * @param businessObjectDefinitionKey the business object definition key * @param includeBusinessObjectDefinitionUpdateHistory a flag to include change event information or not * * @return the business object definition. */ protected BusinessObjectDefinition getBusinessObjectDefinitionImpl(BusinessObjectDefinitionKey businessObjectDefinitionKey, Boolean includeBusinessObjectDefinitionUpdateHistory) { // Perform validation and trim. businessObjectDefinitionHelper.validateBusinessObjectDefinitionKey(businessObjectDefinitionKey); // Retrieve and ensure that a business object definition already exists with the specified key. BusinessObjectDefinitionEntity businessObjectDefinitionEntity = businessObjectDefinitionDaoHelper.getBusinessObjectDefinitionEntity(businessObjectDefinitionKey); // Create and return the business object definition object from the persisted entity. return createBusinessObjectDefinitionFromEntity(businessObjectDefinitionEntity, includeBusinessObjectDefinitionUpdateHistory); } /** * {@inheritDoc} *

* This implementation starts a new transaction. */ @NamespacePermission(fields = "#businessObjectDefinitionKey.namespace", permissions = NamespacePermissionEnum.WRITE) @Override @Transactional(propagation = Propagation.REQUIRES_NEW) public BusinessObjectDefinition deleteBusinessObjectDefinition(BusinessObjectDefinitionKey businessObjectDefinitionKey) { return deleteBusinessObjectDefinitionImpl(businessObjectDefinitionKey); } /** * Deletes a business object definition for the specified name. * * @param businessObjectDefinitionKey the business object definition key * * @return the business object definition that was deleted. */ protected BusinessObjectDefinition deleteBusinessObjectDefinitionImpl(BusinessObjectDefinitionKey businessObjectDefinitionKey) { // Perform validation and trim. businessObjectDefinitionHelper.validateBusinessObjectDefinitionKey(businessObjectDefinitionKey); // Retrieve and ensure that a business object definition already exists with the specified key. BusinessObjectDefinitionEntity businessObjectDefinitionEntity = businessObjectDefinitionDaoHelper.getBusinessObjectDefinitionEntity(businessObjectDefinitionKey); // Delete the business object definition. businessObjectDefinitionDao.delete(businessObjectDefinitionEntity); // Notify the search index that a business object definition must be deleted. LOGGER.info("Delete the business object definition in the search index associated with the business object definition being deleted." + " businessObjectDefinitionId=\"{}\", searchIndexUpdateType=\"{}\"", businessObjectDefinitionEntity.getId(), SEARCH_INDEX_UPDATE_TYPE_DELETE); searchIndexUpdateHelper.modifyBusinessObjectDefinitionInSearchIndex(businessObjectDefinitionEntity, SEARCH_INDEX_UPDATE_TYPE_DELETE); // Create and return the business object definition object from the deleted entity. return createBusinessObjectDefinitionFromEntity(businessObjectDefinitionEntity, false); } @Override public BusinessObjectDefinitionKeys getBusinessObjectDefinitions() { BusinessObjectDefinitionKeys businessObjectDefinitionKeys = new BusinessObjectDefinitionKeys(); businessObjectDefinitionKeys.getBusinessObjectDefinitionKeys().addAll(businessObjectDefinitionDao.getBusinessObjectDefinitionKeys()); return businessObjectDefinitionKeys; } @Override public BusinessObjectDefinitionKeys getBusinessObjectDefinitions(String namespaceCode) { // Validate and trim the namespace code. Assert.hasText(namespaceCode, "A namespace must be specified."); // Retrieve and return the list of business object definitions BusinessObjectDefinitionKeys businessObjectDefinitionKeys = new BusinessObjectDefinitionKeys(); businessObjectDefinitionKeys.getBusinessObjectDefinitionKeys() .addAll(businessObjectDefinitionDao.getBusinessObjectDefinitionKeysByNamespace(namespaceCode.trim())); return businessObjectDefinitionKeys; } @Override public Set getValidFacetFields() { return ImmutableSet.of(TAG_FACET_FIELD); } @Override public BusinessObjectDefinitionSearchResponse searchBusinessObjectDefinitions(BusinessObjectDefinitionSearchRequest request, Set fields) { // Validate the business object definition search fields. validateSearchResponseFields(fields); List tagEntities = new ArrayList<>(); if (!CollectionUtils.isEmpty(request.getBusinessObjectDefinitionSearchFilters())) { // Validate the search request. validateBusinessObjectDefinitionSearchRequest(request); BusinessObjectDefinitionSearchKey businessObjectDefinitionSearchKey = request.getBusinessObjectDefinitionSearchFilters().get(0).getBusinessObjectDefinitionSearchKeys().get(0); TagEntity tagEntity = tagDaoHelper.getTagEntity(businessObjectDefinitionSearchKey.getTagKey()); // If includeTagHierarchy is true, get list of children tag entities down the hierarchy of the specified tag. tagEntities.add(tagEntity); if (BooleanUtils.isTrue(businessObjectDefinitionSearchKey.isIncludeTagHierarchy())) { tagEntities.addAll(tagDaoHelper.getTagChildrenEntities(tagEntity)); } } // Construct business object search response. BusinessObjectDefinitionSearchResponse searchResponse = new BusinessObjectDefinitionSearchResponse(); List businessObjectDefinitions = new ArrayList<>(); searchResponse.setBusinessObjectDefinitions(businessObjectDefinitions); // Retrieve all unique business object definition entities and construct a list of business object definitions based on the requested fields. for (BusinessObjectDefinitionEntity businessObjectDefinition : ImmutableSet .copyOf(businessObjectDefinitionDao.getBusinessObjectDefinitions(tagEntities))) { businessObjectDefinitions.add(createBusinessObjectDefinitionFromEntity(businessObjectDefinition, fields)); } return searchResponse; } /** * Validates the business object definition update request. This method also trims request parameters. * * @param request the request. * * @throws IllegalArgumentException if any validation errors were found. */ private void validateBusinessObjectDefinitionUpdateRequest(BusinessObjectDefinitionUpdateRequest request) { if (request.getDisplayName() != null) { request.setDisplayName(request.getDisplayName().trim()); } // Validate attributes. attributeHelper.validateAttributes(request.getAttributes()); } /** * Validates the business object definition update request. This method also trims request parameters. * * @param request the request. * * @throws IllegalArgumentException if any validation errors were found. */ private void validateBusinessObjectDefinitionDescriptiveInformationUpdateRequest(BusinessObjectDefinitionDescriptiveInformationUpdateRequest request) { if (request.getDisplayName() != null) { request.setDisplayName(request.getDisplayName().trim()); } if (request.getDescriptiveBusinessObjectFormat() != null) { DescriptiveBusinessObjectFormatUpdateRequest descriptiveFormat = request.getDescriptiveBusinessObjectFormat(); descriptiveFormat.setBusinessObjectFormatUsage( alternateKeyHelper.validateStringParameter("business object format usage", descriptiveFormat.getBusinessObjectFormatUsage())); descriptiveFormat.setBusinessObjectFormatFileType( alternateKeyHelper.validateStringParameter("business object format file type", descriptiveFormat.getBusinessObjectFormatFileType())); } } /** * Update and persist the business object definition per specified update request. * * @param businessObjectDefinitionEntity the business object definition entity * @param request the business object definition update request */ private void updateBusinessObjectDefinitionEntity(BusinessObjectDefinitionEntity businessObjectDefinitionEntity, BusinessObjectDefinitionUpdateRequest request) { // Update the entity with the new description value. businessObjectDefinitionEntity.setDescription(request.getDescription()); businessObjectDefinitionEntity.setDisplayName(request.getDisplayName()); // Update the attributes. // Load all existing attribute entities in a map with a "lowercase" attribute name as the key for case insensitivity. Map existingAttributeEntities = new HashMap<>(); for (BusinessObjectDefinitionAttributeEntity attributeEntity : businessObjectDefinitionEntity.getAttributes()) { String mapKey = attributeEntity.getName().toLowerCase(); if (existingAttributeEntities.containsKey(mapKey)) { throw new IllegalStateException(String.format( "Found duplicate attribute with name \"%s\" for business object definition {namespace: \"%s\", businessObjectDefinitionName: \"%s\"}.", mapKey, businessObjectDefinitionEntity.getNamespace().getCode(), businessObjectDefinitionEntity.getName())); } existingAttributeEntities.put(mapKey, attributeEntity); } // Process the list of attributes to determine that business object definition attribute entities should be created, updated, or deleted. List createdAttributeEntities = new ArrayList<>(); List retainedAttributeEntities = new ArrayList<>(); if (!CollectionUtils.isEmpty(request.getAttributes())) { for (Attribute attribute : request.getAttributes()) { // Use a "lowercase" attribute name for case insensitivity. String lowercaseAttributeName = attribute.getName().toLowerCase(); if (existingAttributeEntities.containsKey(lowercaseAttributeName)) { // Check if the attribute value needs to be updated. BusinessObjectDefinitionAttributeEntity attributeEntity = existingAttributeEntities.get(lowercaseAttributeName); if (!StringUtils.equals(attribute.getValue(), attributeEntity.getValue())) { // Update the business object attribute entity. attributeEntity.setValue(attribute.getValue()); } // Add this entity to the list of business object definition attribute entities to be retained. retainedAttributeEntities.add(attributeEntity); } else { // Create a new business object attribute entity. BusinessObjectDefinitionAttributeEntity attributeEntity = new BusinessObjectDefinitionAttributeEntity(); businessObjectDefinitionEntity.getAttributes().add(attributeEntity); attributeEntity.setBusinessObjectDefinition(businessObjectDefinitionEntity); attributeEntity.setName(attribute.getName()); attributeEntity.setValue(attribute.getValue()); // Add this entity to the list of the newly created business object definition attribute entities. retainedAttributeEntities.add(attributeEntity); } } } // Remove any of the currently existing attribute entities that did not get onto the retained entities list. businessObjectDefinitionEntity.getAttributes().retainAll(retainedAttributeEntities); // Add all of the newly created business object definition attribute entities. businessObjectDefinitionEntity.getAttributes().addAll(createdAttributeEntities); // Persist the change event entity saveBusinessObjectDefinitionChangeEvents(businessObjectDefinitionEntity); // Persist the entity. businessObjectDefinitionDao.saveAndRefresh(businessObjectDefinitionEntity); } /** * Update and persist the business object definition descriptive information per specified update request. * * @param businessObjectDefinitionEntity the business object definition entity * @param request the business object definition update request */ private void updateBusinessObjectDefinitionEntityDescriptiveInformation(BusinessObjectDefinitionEntity businessObjectDefinitionEntity, BusinessObjectDefinitionDescriptiveInformationUpdateRequest request) { // Update the entity with the new description value. businessObjectDefinitionEntity.setDescription(request.getDescription()); businessObjectDefinitionEntity.setDisplayName(request.getDisplayName()); // Persist the change event entity saveBusinessObjectDefinitionChangeEvents(businessObjectDefinitionEntity); businessObjectDefinitionDao.saveAndRefresh(businessObjectDefinitionEntity); } /** * Update and persist the business object definition change events * * @param businessObjectDefinitionEntity the business object definition entity */ private void saveBusinessObjectDefinitionChangeEvents(BusinessObjectDefinitionEntity businessObjectDefinitionEntity) { businessObjectDefinitionDaoHelper.saveBusinessObjectDefinitionChangeEvents(businessObjectDefinitionEntity); } /** * Creates a business object definition from the persisted entity. * * @param businessObjectDefinitionEntity the business object definition entity * * @return the business object definition */ private BusinessObjectDefinition createBusinessObjectDefinitionFromEntity(BusinessObjectDefinitionEntity businessObjectDefinitionEntity, Boolean includeBusinessObjectDefinitionUpdateHistory) { // Create a business object definition. BusinessObjectDefinition businessObjectDefinition = new BusinessObjectDefinition(); businessObjectDefinition.setId(businessObjectDefinitionEntity.getId()); businessObjectDefinition.setNamespace(businessObjectDefinitionEntity.getNamespace().getCode()); businessObjectDefinition.setBusinessObjectDefinitionName(businessObjectDefinitionEntity.getName()); businessObjectDefinition.setDescription(businessObjectDefinitionEntity.getDescription()); businessObjectDefinition.setDataProviderName(businessObjectDefinitionEntity.getDataProvider().getName()); businessObjectDefinition.setDisplayName(businessObjectDefinitionEntity.getDisplayName()); // Add attributes. List attributes = new ArrayList<>(); businessObjectDefinition.setAttributes(attributes); for (BusinessObjectDefinitionAttributeEntity attributeEntity : businessObjectDefinitionEntity.getAttributes()) { attributes.add(new Attribute(attributeEntity.getName(), attributeEntity.getValue())); } if (businessObjectDefinitionEntity.getDescriptiveBusinessObjectFormat() != null) { BusinessObjectFormatEntity descriptiveFormatEntity = businessObjectDefinitionEntity.getDescriptiveBusinessObjectFormat(); DescriptiveBusinessObjectFormat descriptiveBusinessObjectFormat = new DescriptiveBusinessObjectFormat(); businessObjectDefinition.setDescriptiveBusinessObjectFormat(descriptiveBusinessObjectFormat); descriptiveBusinessObjectFormat.setBusinessObjectFormatUsage(descriptiveFormatEntity.getUsage()); descriptiveBusinessObjectFormat.setBusinessObjectFormatFileType(descriptiveFormatEntity.getFileType().getCode()); descriptiveBusinessObjectFormat.setBusinessObjectFormatVersion(descriptiveFormatEntity.getBusinessObjectFormatVersion()); } // Add sample data files. List sampleDataFiles = new ArrayList<>(); businessObjectDefinition.setSampleDataFiles(sampleDataFiles); for (BusinessObjectDefinitionSampleDataFileEntity sampleDataFileEntity : businessObjectDefinitionEntity.getSampleDataFiles()) { sampleDataFiles.add(new SampleDataFile(sampleDataFileEntity.getDirectoryPath(), sampleDataFileEntity.getFileName())); } // Add auditable fields. businessObjectDefinition.setCreatedByUserId(businessObjectDefinitionEntity.getCreatedBy()); businessObjectDefinition.setLastUpdatedByUserId(businessObjectDefinitionEntity.getUpdatedBy()); businessObjectDefinition.setLastUpdatedOn(HerdDateUtils.getXMLGregorianCalendarValue(businessObjectDefinitionEntity.getUpdatedOn())); // Add change events. final List businessObjectDefinitionChangeEvents = new ArrayList<>(); if (BooleanUtils.isTrue(includeBusinessObjectDefinitionUpdateHistory)) { businessObjectDefinitionEntity.getChangeEvents().forEach(businessObjectDefinitionChangeEventEntity -> { DescriptiveBusinessObjectFormatUpdateRequest descriptiveBusinessObjectFormatUpdateRequest = null; if (businessObjectDefinitionChangeEventEntity.getFileType() != null) { descriptiveBusinessObjectFormatUpdateRequest = new DescriptiveBusinessObjectFormatUpdateRequest(businessObjectDefinitionChangeEventEntity.getUsage(), businessObjectDefinitionChangeEventEntity.getFileType()); } businessObjectDefinitionChangeEvents.add(new BusinessObjectDefinitionChangeEvent(businessObjectDefinitionChangeEventEntity.getDisplayName(), businessObjectDefinitionChangeEventEntity.getDescription(), descriptiveBusinessObjectFormatUpdateRequest, HerdDateUtils.getXMLGregorianCalendarValue(businessObjectDefinitionChangeEventEntity.getCreatedOn()), businessObjectDefinitionChangeEventEntity.getCreatedBy())); }); } businessObjectDefinition.setBusinessObjectDefinitionChangeEvents(businessObjectDefinitionChangeEvents); return businessObjectDefinition; } /** * Creates a light-weight business object definition from its persisted entity based on a set of requested fields. * * @param businessObjectDefinitionEntity the specified business object definition entity * @param fields the set of requested fields * * @return the light-weight business object definition */ private BusinessObjectDefinition createBusinessObjectDefinitionFromEntity(BusinessObjectDefinitionEntity businessObjectDefinitionEntity, Set fields) { BusinessObjectDefinition definition = new BusinessObjectDefinition(); // Populate namespace and business object definition name fields by default definition.setNamespace(businessObjectDefinitionEntity.getNamespace().getCode()); definition.setBusinessObjectDefinitionName(businessObjectDefinitionEntity.getName()); // Decorate object with only the required fields if (fields.contains(DATA_PROVIDER_NAME_FIELD)) { definition.setDataProviderName(businessObjectDefinitionEntity.getDataProvider().getName()); } if (fields.contains(SHORT_DESCRIPTION_FIELD)) { // Get the configured value for short description's length Integer shortDescMaxLength = configurationHelper.getProperty(ConfigurationValue.BUSINESS_OBJECT_DEFINITION_SHORT_DESCRIPTION_LENGTH, Integer.class); definition.setShortDescription(HerdStringUtils.getShortDescription(businessObjectDefinitionEntity.getDescription(), shortDescMaxLength)); } if (fields.contains(DISPLAY_NAME_FIELD)) { definition.setDisplayName(businessObjectDefinitionEntity.getDisplayName()); } return definition; } @Override public Set getValidSearchResponseFields() { return ImmutableSet.of(DATA_PROVIDER_NAME_FIELD, SHORT_DESCRIPTION_FIELD, DISPLAY_NAME_FIELD); } /** * Validate the business object definition search request. This method also trims the request parameters. * * @param businessObjectDefinitionSearchRequest the business object definition search request */ private void validateBusinessObjectDefinitionSearchRequest(BusinessObjectDefinitionSearchRequest businessObjectDefinitionSearchRequest) { if (CollectionUtils.size(businessObjectDefinitionSearchRequest.getBusinessObjectDefinitionSearchFilters()) == 1 && businessObjectDefinitionSearchRequest.getBusinessObjectDefinitionSearchFilters().get(0) != null) { // Get the business object definition search filter. BusinessObjectDefinitionSearchFilter businessObjectDefinitionSearchFilter = businessObjectDefinitionSearchRequest.getBusinessObjectDefinitionSearchFilters().get(0); Assert.isTrue(CollectionUtils.size(businessObjectDefinitionSearchFilter.getBusinessObjectDefinitionSearchKeys()) == 1 && businessObjectDefinitionSearchFilter.getBusinessObjectDefinitionSearchKeys().get(0) != null, "Exactly one business object definition search key must be specified."); // Get the tag search key. BusinessObjectDefinitionSearchKey businessObjectDefinitionSearchKey = businessObjectDefinitionSearchFilter.getBusinessObjectDefinitionSearchKeys().get(0); tagHelper.validateTagKey(businessObjectDefinitionSearchKey.getTagKey()); } else { Assert.isTrue(CollectionUtils.size(businessObjectDefinitionSearchRequest.getBusinessObjectDefinitionSearchFilters()) == 1 && businessObjectDefinitionSearchRequest.getBusinessObjectDefinitionSearchFilters().get(0) != null, "Exactly one business object definition search filter must be specified."); } } @Override public void updateBusinessObjectDefinitionEntitySampleFile(BusinessObjectDefinitionKey businessObjectDefinitionKey, BusinessObjectDefinitionSampleFileUpdateDto businessObjectDefinitionSampleFileUpdateDto) { String path = businessObjectDefinitionSampleFileUpdateDto.getPath(); String fileName = businessObjectDefinitionSampleFileUpdateDto.getFileName(); long fileSize = businessObjectDefinitionSampleFileUpdateDto.getFileSize(); // Validate business object key businessObjectDefinitionHelper.validateBusinessObjectDefinitionKey(businessObjectDefinitionKey); // Validate file name Assert.hasText(fileName, "A file name must be specified."); BusinessObjectDefinitionEntity businessObjectDefinitionEntity = businessObjectDefinitionDaoHelper.getBusinessObjectDefinitionEntity(businessObjectDefinitionKey); Collection sampleFiles = businessObjectDefinitionEntity.getSampleDataFiles(); boolean found = false; for (BusinessObjectDefinitionSampleDataFileEntity sampleDataFieEntity : sampleFiles) { // Assume the path is the same for this business object definition if (sampleDataFieEntity.getFileName().equals(fileName)) { found = true; sampleDataFieEntity.setFileSizeBytes(fileSize); businessObjectDefinitionDao.saveAndRefresh(businessObjectDefinitionEntity); break; } } // Create a new entity when not found if (!found) { StorageEntity storageEntity = storageDaoHelper.getStorageEntity(StorageEntity.SAMPLE_DATA_FILE_STORAGE); BusinessObjectDefinitionSampleDataFileEntity sampleDataFileEntity = new BusinessObjectDefinitionSampleDataFileEntity(); sampleDataFileEntity.setStorage(storageEntity); sampleDataFileEntity.setBusinessObjectDefinition(businessObjectDefinitionEntity); sampleDataFileEntity.setDirectoryPath(path); sampleDataFileEntity.setFileName(fileName); sampleDataFileEntity.setFileSizeBytes(fileSize); businessObjectDefinitionEntity.getSampleDataFiles().add(sampleDataFileEntity); businessObjectDefinitionDao.saveAndRefresh(businessObjectDefinitionEntity); } // Notify the search index that a business object definition must be updated. LOGGER.info("Modify the business object definition in the search index associated with the business object definition being updated." + " businessObjectDefinitionId=\"{}\", searchIndexUpdateType=\"{}\"", businessObjectDefinitionEntity.getId(), SEARCH_INDEX_UPDATE_TYPE_UPDATE); searchIndexUpdateHelper.modifyBusinessObjectDefinitionInSearchIndex(businessObjectDefinitionEntity, SEARCH_INDEX_UPDATE_TYPE_UPDATE); } /** * {@inheritDoc} *

* This implementation starts a new transaction. */ @Override @Transactional(propagation = Propagation.REQUIRES_NEW) public void updateSearchIndexDocumentBusinessObjectDefinition(SearchIndexUpdateDto searchIndexUpdateDto) { updateSearchIndexDocumentBusinessObjectDefinitionImpl(searchIndexUpdateDto); } /** * Updates the search index document representation of the business object definition. * * @param searchIndexUpdateDto the SearchIndexUpdateDto object */ protected void updateSearchIndexDocumentBusinessObjectDefinitionImpl(SearchIndexUpdateDto searchIndexUpdateDto) { final String indexName = configurationHelper.getProperty(ConfigurationValue.ELASTICSEARCH_BDEF_INDEX_NAME, String.class); final String documentType = configurationHelper.getProperty(ConfigurationValue.ELASTICSEARCH_BDEF_DOCUMENT_TYPE, String.class); String modificationType = searchIndexUpdateDto.getModificationType(); List ids = searchIndexUpdateDto.getBusinessObjectDefinitionIds(); LOGGER.info("Updating the search index document representation(s) of the business object definition(s)." + " businessObjectDefinitionIds=[{}], searchIndexUpdateType=\"{}\"", ids.stream().map(String::valueOf).collect(Collectors.joining(", ")), modificationType); // Start at index 0 int fromIndex = 0; // Process documents until the ids are all updated while (fromIndex < ids.size()) { // Process based on a document chunk size, if the id.size is greater than the chunk size then use the chunk size int toIndex = ids.size() > fromIndex + UPDATE_SEARCH_INDEX_DOCUMENT_CHUNK_SIZE ? fromIndex + UPDATE_SEARCH_INDEX_DOCUMENT_CHUNK_SIZE : ids.size(); // Switch on the type of CRUD modification to be done switch (modificationType) { case SEARCH_INDEX_UPDATE_TYPE_CREATE: // Create a search index document indexFunctionsDao.createIndexDocuments(indexName, documentType, convertBusinessObjectDefinitionEntityListToJSONStringMap( businessObjectDefinitionDao.getAllBusinessObjectDefinitionsByIds(ids.subList(fromIndex, toIndex)))); break; case SEARCH_INDEX_UPDATE_TYPE_UPDATE: // Update a search index document indexFunctionsDao.updateIndexDocuments(indexName, documentType, convertBusinessObjectDefinitionEntityListToJSONStringMap( businessObjectDefinitionDao.getAllBusinessObjectDefinitionsByIds(ids.subList(fromIndex, toIndex)))); break; case SEARCH_INDEX_UPDATE_TYPE_DELETE: // Delete a search index document indexFunctionsDao.deleteIndexDocuments(indexName, documentType, ids.subList(fromIndex, toIndex)); break; default: LOGGER.warn("Unknown modification type received."); break; } // Set the from index to the toIndex fromIndex = toIndex; } LOGGER.info("Finished processing {} documents", ids.size()); } /** * Private method to convert a business object definition entity list to a list of JSON strings. * * @param businessObjectDefinitionEntities the list of business object definitions * * @return Map of key, business object definition ids, and value, business object definition entity as JSON string */ private Map convertBusinessObjectDefinitionEntityListToJSONStringMap(List businessObjectDefinitionEntities) { LOGGER.info("List size is {}.", businessObjectDefinitionEntities.size()); Map businessObjectDefinitionJSONMap = new HashMap<>(); businessObjectDefinitionEntities.forEach(businessObjectDefinitionEntity -> { // Fetch Join with .size() businessObjectDefinitionEntity.getAttributes().size(); businessObjectDefinitionEntity.getBusinessObjectDefinitionTags().size(); businessObjectDefinitionEntity.getBusinessObjectFormats().size(); businessObjectDefinitionEntity.getColumns().size(); businessObjectDefinitionEntity.getSampleDataFiles().size(); String jsonString = businessObjectDefinitionHelper.safeObjectMapperWriteValueAsString(businessObjectDefinitionEntity); if (StringUtils.isNotEmpty(jsonString)) { businessObjectDefinitionJSONMap.put(businessObjectDefinitionEntity.getId().toString(), jsonString); } else { LOGGER.warn("Business Object Definition Entity {} jsonString is empty.", businessObjectDefinitionEntity.getId()); } }); return businessObjectDefinitionJSONMap; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy