/* * 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_UPDATE; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import com.google.common.collect.ImmutableSet; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.IterableUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; import org.finra.herd.dao.BusinessObjectDefinitionColumnDao; import org.finra.herd.dao.BusinessObjectDefinitionDao; import org.finra.herd.dao.SchemaColumnDao; import org.finra.herd.dao.config.DaoSpringModuleConfig; import org.finra.herd.model.AlreadyExistsException; import org.finra.herd.model.ObjectNotFoundException; import org.finra.herd.model.annotation.PublishJmsMessages; import org.finra.herd.model.api.xml.BusinessObjectDefinitionColumn; import org.finra.herd.model.api.xml.BusinessObjectDefinitionColumnCreateRequest; import org.finra.herd.model.api.xml.BusinessObjectDefinitionColumnKey; import org.finra.herd.model.api.xml.BusinessObjectDefinitionColumnKeys; import org.finra.herd.model.api.xml.BusinessObjectDefinitionColumnSearchFilter; import org.finra.herd.model.api.xml.BusinessObjectDefinitionColumnSearchKey; import org.finra.herd.model.api.xml.BusinessObjectDefinitionColumnSearchRequest; import org.finra.herd.model.api.xml.BusinessObjectDefinitionColumnSearchResponse; import org.finra.herd.model.api.xml.BusinessObjectDefinitionColumnUpdateRequest; import org.finra.herd.model.api.xml.BusinessObjectDefinitionKey; import org.finra.herd.model.jpa.BusinessObjectDefinitionColumnEntity; import org.finra.herd.model.jpa.BusinessObjectDefinitionEntity; import org.finra.herd.model.jpa.SchemaColumnEntity; import org.finra.herd.service.BusinessObjectDefinitionColumnService; import org.finra.herd.service.SearchableService; import org.finra.herd.service.helper.AlternateKeyHelper; import org.finra.herd.service.helper.BusinessObjectDefinitionColumnDaoHelper; import org.finra.herd.service.helper.BusinessObjectDefinitionDaoHelper; import org.finra.herd.service.helper.BusinessObjectDefinitionHelper; import org.finra.herd.service.helper.SearchIndexUpdateHelper; /** * The business object definition column service implementation. */ @Service @Transactional(value = DaoSpringModuleConfig.HERD_TRANSACTION_MANAGER_BEAN_NAME) public class BusinessObjectDefinitionColumnServiceImpl implements BusinessObjectDefinitionColumnService, SearchableService { // Constant to hold the schema column name field option for the business object definition column search public static final String SCHEMA_COLUMN_NAME_FIELD = "schemaColumnName".toLowerCase(); // Constant to hold the description field option for the business object definition column search public static final String DESCRIPTION_FIELD = "description"; @Autowired private AlternateKeyHelper alternateKeyHelper; @Autowired private BusinessObjectDefinitionColumnDao businessObjectDefinitionColumnDao; @Autowired private BusinessObjectDefinitionColumnDaoHelper businessObjectDefinitionColumnDaoHelper; @Autowired private BusinessObjectDefinitionDao businessObjectDefinitionDao; @Autowired private BusinessObjectDefinitionDaoHelper businessObjectDefinitionDaoHelper; @Autowired private BusinessObjectDefinitionHelper businessObjectDefinitionHelper; @Autowired private SchemaColumnDao schemaColumnDao; @Autowired private SearchIndexUpdateHelper searchIndexUpdateHelper; @PublishJmsMessages @Override public BusinessObjectDefinitionColumn createBusinessObjectDefinitionColumn(BusinessObjectDefinitionColumnCreateRequest request) { // Validate and trim the business object definition column create request. validateBusinessObjectDefinitionColumnCreateRequest(request); // Get the business object definition key. BusinessObjectDefinitionKey businessObjectDefinitionKey = businessObjectDefinitionHelper.getBusinessObjectDefinitionKey(request.getBusinessObjectDefinitionColumnKey()); // Get the business object definition and ensure it exists. BusinessObjectDefinitionEntity businessObjectDefinitionEntity = businessObjectDefinitionDaoHelper.getBusinessObjectDefinitionEntity(businessObjectDefinitionKey); // Ensure a business object definition column with the specified name doesn't already exist for the business object definition. if (businessObjectDefinitionColumnDao.getBusinessObjectDefinitionColumnByBusinessObjectDefinitionColumnName(businessObjectDefinitionEntity, request.getBusinessObjectDefinitionColumnKey().getBusinessObjectDefinitionColumnName()) != null) { throw new AlreadyExistsException(String.format( "Unable to create business object definition column with name \"%s\" because it already exists for the business object definition {%s}.", request.getBusinessObjectDefinitionColumnKey().getBusinessObjectDefinitionColumnName(), businessObjectDefinitionHelper.businessObjectDefinitionKeyToString(businessObjectDefinitionKey))); } // Retrieve schema column entities from all format instances for the business object definition that match the specified schema column name. Collection<SchemaColumnEntity> schemaColumnEntities = schemaColumnDao.getSchemaColumns(businessObjectDefinitionEntity, request.getSchemaColumnName()); // Ensure that exists at least one schema column that matches the specified schema column name. if (CollectionUtils.isEmpty(schemaColumnEntities)) { if (businessObjectDefinitionEntity.getDescriptiveBusinessObjectFormat() == null) { throw new ObjectNotFoundException(String.format("Unable to create business object definition column because there are no format schema " + "columns with name \"%s\" for the business object definition {%s}.", request.getSchemaColumnName(), businessObjectDefinitionHelper.businessObjectDefinitionKeyToString(businessObjectDefinitionKey))); } else { throw new ObjectNotFoundException(String.format("Unable to create business object definition column because there are no format schema " + "columns with name \"%s\" in the descriptive business object format for the business object definition {%s}.", request.getSchemaColumnName(), businessObjectDefinitionHelper.businessObjectDefinitionKeyToString(businessObjectDefinitionKey))); } } // Ensure a business object definition column with the specified schema column name doesn't already exist for this business object definition. for (SchemaColumnEntity schemaColumnEntity : schemaColumnEntities) { if (schemaColumnEntity.getBusinessObjectDefinitionColumn() != null) { throw new AlreadyExistsException(String.format( "Unable to create business object definition column because a business object definition column " + "with schema column name \"%s\" already exists for the business object definition {%s}.", request.getSchemaColumnName(), businessObjectDefinitionHelper.businessObjectDefinitionKeyToString(businessObjectDefinitionKey))); } } // Create a business object definition column entity from the request information. BusinessObjectDefinitionColumnEntity businessObjectDefinitionColumnEntity = createBusinessObjectDefinitionColumnEntity(businessObjectDefinitionEntity, request); // Link schema columns with the business object definition column. for (SchemaColumnEntity schemaColumnEntity : schemaColumnEntities) { schemaColumnEntity.setBusinessObjectDefinitionColumn(businessObjectDefinitionColumnEntity); } // Persist the new entity. businessObjectDefinitionColumnEntity = businessObjectDefinitionColumnDao.saveAndRefresh(businessObjectDefinitionColumnEntity); // Notify the search index that a business object definition must be updated. searchIndexUpdateHelper.modifyBusinessObjectDefinitionInSearchIndex(businessObjectDefinitionEntity, SEARCH_INDEX_UPDATE_TYPE_UPDATE); // Create and return the business object definition column object from the persisted entity. return createBusinessObjectDefinitionColumnFromEntity(businessObjectDefinitionColumnEntity, true, getValidSearchResponseFields()); } @PublishJmsMessages @Override public BusinessObjectDefinitionColumn deleteBusinessObjectDefinitionColumn(BusinessObjectDefinitionColumnKey businessObjectDefinitionColumnKey) { // Validate and trim the business object definition column key. validateBusinessObjectDefinitionColumnKey(businessObjectDefinitionColumnKey); // Retrieve and ensure that a business object definition column exists with the business object definition. BusinessObjectDefinitionColumnEntity businessObjectDefinitionColumnEntity = businessObjectDefinitionColumnDaoHelper.getBusinessObjectDefinitionColumnEntity(businessObjectDefinitionColumnKey); // Unlink schema columns from the business object definition column. for (SchemaColumnEntity schemaColumnEntity : businessObjectDefinitionColumnEntity.getSchemaColumns()) { schemaColumnEntity.setBusinessObjectDefinitionColumn(null); } // Delete the business object definition column. BusinessObjectDefinitionEntity businessObjectDefinitionEntity = businessObjectDefinitionColumnEntity.getBusinessObjectDefinition(); businessObjectDefinitionEntity.getColumns().remove(businessObjectDefinitionColumnEntity); businessObjectDefinitionDao.saveAndRefresh(businessObjectDefinitionEntity); // Notify the search index that a business object definition must be updated. searchIndexUpdateHelper.modifyBusinessObjectDefinitionInSearchIndex(businessObjectDefinitionEntity, SEARCH_INDEX_UPDATE_TYPE_UPDATE); // Create and return the business object definition column object from the deleted entity. return createBusinessObjectDefinitionColumnFromEntity(businessObjectDefinitionColumnEntity, true, getValidSearchResponseFields()); } @Override public BusinessObjectDefinitionColumn getBusinessObjectDefinitionColumn(BusinessObjectDefinitionColumnKey businessObjectDefinitionColumnKey) { // Validate and trim the business object definition column key. validateBusinessObjectDefinitionColumnKey(businessObjectDefinitionColumnKey); // Retrieve and ensure that a business object definition column exists with the business object definition. BusinessObjectDefinitionColumnEntity businessObjectDefinitionColumnEntity = businessObjectDefinitionColumnDaoHelper.getBusinessObjectDefinitionColumnEntity(businessObjectDefinitionColumnKey); // Create and return the business object definition column object from the persisted entity. return createBusinessObjectDefinitionColumnFromEntity(businessObjectDefinitionColumnEntity, true, getValidSearchResponseFields()); } @Override public BusinessObjectDefinitionColumnKeys getBusinessObjectDefinitionColumns(BusinessObjectDefinitionKey businessObjectDefinitionKey) { // Validate and trim the business object definition key. businessObjectDefinitionHelper.validateBusinessObjectDefinitionKey(businessObjectDefinitionKey); // Retrieve the business object definition and ensure it exists. BusinessObjectDefinitionEntity businessObjectDefinitionEntity = businessObjectDefinitionDaoHelper.getBusinessObjectDefinitionEntity(businessObjectDefinitionKey); // Create and populate a list of business object definition column keys. BusinessObjectDefinitionColumnKeys businessObjectDefinitionColumnKeys = new BusinessObjectDefinitionColumnKeys(); for (BusinessObjectDefinitionColumnEntity businessObjectDefinitionColumnEntity : businessObjectDefinitionEntity.getColumns()) { businessObjectDefinitionColumnKeys.getBusinessObjectDefinitionColumnKeys() .add(getBusinessObjectDefinitionColumnKey(businessObjectDefinitionColumnEntity)); } return businessObjectDefinitionColumnKeys; } /** * Returns the valid search fields. * * @return valid search fields */ @Override public Set<String> getValidSearchResponseFields() { return ImmutableSet.of(SCHEMA_COLUMN_NAME_FIELD, DESCRIPTION_FIELD); } @Override public BusinessObjectDefinitionColumnSearchResponse searchBusinessObjectDefinitionColumns(BusinessObjectDefinitionColumnSearchRequest request, Set<String> fields) { // Validate search request validateBusinessObjectDefinitionColumnSearchRequest(request); // Validate the fields validateSearchResponseFields(fields); // Only a single search filter and a single search key is allowed at this time. // Use the first search filter and first search key in the filter and keys list. BusinessObjectDefinitionKey businessObjectDefinitionKey = new BusinessObjectDefinitionKey( request.getBusinessObjectDefinitionColumnSearchFilters().get(0).getBusinessObjectDefinitionColumnSearchKeys().get(0).getNamespace(), request.getBusinessObjectDefinitionColumnSearchFilters().get(0).getBusinessObjectDefinitionColumnSearchKeys().get(0) .getBusinessObjectDefinitionName()); // Retrieve the business object definition and ensure it exists. BusinessObjectDefinitionEntity businessObjectDefinitionEntity = businessObjectDefinitionDaoHelper.getBusinessObjectDefinitionEntity(businessObjectDefinitionKey); return new BusinessObjectDefinitionColumnSearchResponse(businessObjectDefinitionEntity.getColumns().stream() .map(businessObjectDefinitionColumnEntity -> createBusinessObjectDefinitionColumnFromEntity(businessObjectDefinitionColumnEntity, false, fields)) .collect(Collectors.toList())); } @PublishJmsMessages @Override public BusinessObjectDefinitionColumn updateBusinessObjectDefinitionColumn(BusinessObjectDefinitionColumnKey businessObjectDefinitionColumnKey, BusinessObjectDefinitionColumnUpdateRequest request) { // Validate and trim the business object definition column key. validateBusinessObjectDefinitionColumnKey(businessObjectDefinitionColumnKey); // Validate and trim the business object definition column update request. validateBusinessObjectDefinitionColumnUpdateRequest(request); // Retrieve and ensure that a business object definition column exists with the business object definition. BusinessObjectDefinitionColumnEntity businessObjectDefinitionColumnEntity = businessObjectDefinitionColumnDaoHelper.getBusinessObjectDefinitionColumnEntity(businessObjectDefinitionColumnKey); // Update the entity with the new values. businessObjectDefinitionColumnEntity.setDescription(request.getDescription()); // Persist the entity. businessObjectDefinitionColumnEntity = businessObjectDefinitionColumnDao.saveAndRefresh(businessObjectDefinitionColumnEntity); // Notify the search index that a business object definition must be updated. searchIndexUpdateHelper .modifyBusinessObjectDefinitionInSearchIndex(businessObjectDefinitionColumnEntity.getBusinessObjectDefinition(), SEARCH_INDEX_UPDATE_TYPE_UPDATE); // Create and return the business object definition column object from the persisted entity. return createBusinessObjectDefinitionColumnFromEntity(businessObjectDefinitionColumnEntity, true, getValidSearchResponseFields()); } /** * Creates a new business object definition column entity from the business object definition entity and the request information. * * @param businessObjectDefinitionEntity the business object definition entity * @param request the business object definition column create request * * @return the newly created business object definition column entity */ private BusinessObjectDefinitionColumnEntity createBusinessObjectDefinitionColumnEntity(BusinessObjectDefinitionEntity businessObjectDefinitionEntity, BusinessObjectDefinitionColumnCreateRequest request) { BusinessObjectDefinitionColumnEntity businessObjectDefinitionColumnEntity = new BusinessObjectDefinitionColumnEntity(); businessObjectDefinitionColumnEntity.setBusinessObjectDefinition(businessObjectDefinitionEntity); businessObjectDefinitionColumnEntity.setName(request.getBusinessObjectDefinitionColumnKey().getBusinessObjectDefinitionColumnName()); businessObjectDefinitionColumnEntity.setDescription(request.getDescription()); return businessObjectDefinitionColumnEntity; } /** * Creates a business object definition column from the persisted entity. * * @param businessObjectDefinitionColumnEntity the business object definition column entity * @param includeId boolean value indicating whether or not to include the id * @param fields set of field parameters to include on the business object definition column * * @return the business object definition column */ private BusinessObjectDefinitionColumn createBusinessObjectDefinitionColumnFromEntity( BusinessObjectDefinitionColumnEntity businessObjectDefinitionColumnEntity, boolean includeId, Set<String> fields) { BusinessObjectDefinitionColumn businessObjectDefinitionColumn = new BusinessObjectDefinitionColumn(); if (includeId) { businessObjectDefinitionColumn.setId(businessObjectDefinitionColumnEntity.getId()); } businessObjectDefinitionColumn.setBusinessObjectDefinitionColumnKey(getBusinessObjectDefinitionColumnKey(businessObjectDefinitionColumnEntity)); if (fields.contains(DESCRIPTION_FIELD)) { businessObjectDefinitionColumn.setDescription(businessObjectDefinitionColumnEntity.getDescription()); } if (fields.contains(SCHEMA_COLUMN_NAME_FIELD) && CollectionUtils.isNotEmpty(businessObjectDefinitionColumnEntity.getSchemaColumns())) { businessObjectDefinitionColumn.setSchemaColumnName(IterableUtils.get(businessObjectDefinitionColumnEntity.getSchemaColumns(), 0).getName()); } return businessObjectDefinitionColumn; } /** * Creates a business object definition column key from the entity. * * @param businessObjectDefinitionColumnEntity the business object definition entity * * @return the business object definition column key */ private BusinessObjectDefinitionColumnKey getBusinessObjectDefinitionColumnKey(BusinessObjectDefinitionColumnEntity businessObjectDefinitionColumnEntity) { return new BusinessObjectDefinitionColumnKey(businessObjectDefinitionColumnEntity.getBusinessObjectDefinition().getNamespace().getCode(), businessObjectDefinitionColumnEntity.getBusinessObjectDefinition().getName(), businessObjectDefinitionColumnEntity.getName()); } /** * Validates the business object definition column create request. This method also trims the request parameters. * * @param request the business object definition column create request */ private void validateBusinessObjectDefinitionColumnCreateRequest(BusinessObjectDefinitionColumnCreateRequest request) { Assert.notNull(request, "A business object definition column create request must be specified."); validateBusinessObjectDefinitionColumnKey(request.getBusinessObjectDefinitionColumnKey()); Assert.hasText(request.getSchemaColumnName(), "A schema column name must be specified."); request.setSchemaColumnName(request.getSchemaColumnName().trim()); } /** * Validates the business object definition column key. This method also trims the key parameters. * * @param key the business object definition column key * * @throws IllegalArgumentException if any validation errors were found */ private void validateBusinessObjectDefinitionColumnKey(BusinessObjectDefinitionColumnKey key) throws IllegalArgumentException { Assert.notNull(key, "A business object data attribute key must be specified."); key.setNamespace(alternateKeyHelper.validateStringParameter("namespace", key.getNamespace())); key.setBusinessObjectDefinitionName( alternateKeyHelper.validateStringParameter("business object definition name", key.getBusinessObjectDefinitionName())); key.setBusinessObjectDefinitionColumnName( alternateKeyHelper.validateStringParameter("business object definition column name", key.getBusinessObjectDefinitionColumnName())); } /** * Validates the business object definition column search request. * * @param request the business object definition column search request * * @throws IllegalArgumentException if any validation errors were found */ private void validateBusinessObjectDefinitionColumnSearchRequest(BusinessObjectDefinitionColumnSearchRequest request) throws IllegalArgumentException { // Validate the request Assert.notNull(request, "A business object definition column search request must be specified."); // Validate the search filters List<BusinessObjectDefinitionColumnSearchFilter> businessObjectDefinitionColumnSearchFilters = request.getBusinessObjectDefinitionColumnSearchFilters(); Assert.isTrue(CollectionUtils.size(businessObjectDefinitionColumnSearchFilters) == 1 && businessObjectDefinitionColumnSearchFilters.get(0) != null, "Exactly one business object definition column search filter must be specified."); // Validate the search keys List<BusinessObjectDefinitionColumnSearchKey> businessObjectDefinitionColumnSearchKeys = businessObjectDefinitionColumnSearchFilters.get(0).getBusinessObjectDefinitionColumnSearchKeys(); Assert.isTrue(CollectionUtils.size(businessObjectDefinitionColumnSearchKeys) == 1 && businessObjectDefinitionColumnSearchKeys.get(0) != null, "Exactly one business object definition column search key must be specified."); // Get the search key BusinessObjectDefinitionColumnSearchKey businessObjectDefinitionColumnSearchKey = businessObjectDefinitionColumnSearchKeys.get(0); // Validate the namespace and the business object definition businessObjectDefinitionColumnSearchKey .setNamespace(alternateKeyHelper.validateStringParameter("namespace", businessObjectDefinitionColumnSearchKey.getNamespace())); businessObjectDefinitionColumnSearchKey.setBusinessObjectDefinitionName(alternateKeyHelper .validateStringParameter("business object definition name", businessObjectDefinitionColumnSearchKey.getBusinessObjectDefinitionName())); } /** * Validates the business object definition column update request. This method also trims the request parameters. * * @param request the business object definition column update request */ private void validateBusinessObjectDefinitionColumnUpdateRequest(BusinessObjectDefinitionColumnUpdateRequest request) { Assert.notNull(request, "A business object definition column update request must be specified."); } }