/*
* 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.ArrayList;
import java.util.List;
import java.util.Set;
import com.google.common.collect.ImmutableSet;
import org.apache.commons.lang3.StringUtils;
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.BusinessObjectDefinitionDao;
import org.finra.herd.dao.TagDao;
import org.finra.herd.dao.TagTypeDao;
import org.finra.herd.dao.config.DaoSpringModuleConfig;
import org.finra.herd.model.AlreadyExistsException;
import org.finra.herd.model.annotation.PublishJmsMessages;
import org.finra.herd.model.api.xml.TagType;
import org.finra.herd.model.api.xml.TagTypeCreateRequest;
import org.finra.herd.model.api.xml.TagTypeKey;
import org.finra.herd.model.api.xml.TagTypeKeys;
import org.finra.herd.model.api.xml.TagTypeSearchRequest;
import org.finra.herd.model.api.xml.TagTypeSearchResponse;
import org.finra.herd.model.api.xml.TagTypeUpdateRequest;
import org.finra.herd.model.jpa.TagEntity;
import org.finra.herd.model.jpa.TagTypeEntity;
import org.finra.herd.service.SearchableService;
import org.finra.herd.service.TagTypeService;
import org.finra.herd.service.helper.AlternateKeyHelper;
import org.finra.herd.service.helper.SearchIndexUpdateHelper;
import org.finra.herd.service.helper.TagTypeDaoHelper;
import org.finra.herd.service.helper.TagTypeHelper;
/**
* The tag type service implementation.
*/
@Service
@Transactional(value = DaoSpringModuleConfig.HERD_TRANSACTION_MANAGER_BEAN_NAME)
public class TagTypeServiceImpl implements TagTypeService, SearchableService
{
// Constant to hold the description field option for the search response.
public final static String DESCRIPTION_FIELD = "description".toLowerCase();
// Constant to hold the display name field option for the search response.
public final static String DISPLAY_NAME_FIELD = "displayName".toLowerCase();
// Constant to hold the tag type order field option for the search response.
public final static String TAG_TYPE_ORDER_FIELD = "tagTypeOrder".toLowerCase();
@Autowired
private AlternateKeyHelper alternateKeyHelper;
@Autowired
private BusinessObjectDefinitionDao businessObjectDefinitionDao;
@Autowired
private SearchIndexUpdateHelper searchIndexUpdateHelper;
@Autowired
private TagDao tagDao;
@Autowired
private TagTypeDao tagTypeDao;
@Autowired
private TagTypeDaoHelper tagTypeDaoHelper;
@Autowired
private TagTypeHelper tagTypeHelper;
@Override
public TagType createTagType(TagTypeCreateRequest request)
{
// Validate and trim the request parameters.
validateTagTypeCreateRequest(request);
// Validate the tag type does not already exist in the database.
if (tagTypeDao.getTagTypeByKey(request.getTagTypeKey()) != null)
{
throw new AlreadyExistsException(
String.format("Unable to create tag type with code \"%s\" because it already exists.", request.getTagTypeKey().getTagTypeCode()));
}
// Validate the display name does not already exist in the database
tagTypeDaoHelper.assertTagTypeDisplayNameDoesNotExist(request.getDisplayName());
// Create and persist a new tag type entity from the request information.
TagTypeEntity tagTypeEntity = createTagTypeEntity(request);
// Create and return the tag type object from the persisted entity.
return createTagTypeFromEntity(tagTypeEntity);
}
@Override
public TagType deleteTagType(TagTypeKey tagTypeKey)
{
// Perform validation and trim.
tagTypeHelper.validateTagTypeKey(tagTypeKey);
// Retrieve and ensure that a tag type already exists with the specified key.
TagTypeEntity tagTypeEntity = tagTypeDaoHelper.getTagTypeEntity(tagTypeKey);
// Delete the tag type.
tagTypeDao.delete(tagTypeEntity);
// Create and return the tag type object from the deleted entity.
return createTagTypeFromEntity(tagTypeEntity);
}
@Override
public TagType getTagType(TagTypeKey tagTypeKey)
{
// Perform validation and trim.
tagTypeHelper.validateTagTypeKey(tagTypeKey);
// Retrieve and ensure that a tag type already exists with the specified key.
TagTypeEntity tagTypeEntity = tagTypeDaoHelper.getTagTypeEntity(tagTypeKey);
// Create and return the tag type object from the persisted entity.
return createTagTypeFromEntity(tagTypeEntity);
}
@Override
public TagTypeKeys getTagTypes()
{
return new TagTypeKeys(tagTypeDao.getTagTypeKeys());
}
@Override
public Set<String> getValidSearchResponseFields()
{
return ImmutableSet.of(DISPLAY_NAME_FIELD, TAG_TYPE_ORDER_FIELD, DESCRIPTION_FIELD);
}
@Override
public TagTypeSearchResponse searchTagTypes(TagTypeSearchRequest request, Set<String> fields)
{
// Validate the request.
Assert.notNull(request, "A tag type search request must be specified.");
// Validate and trim the search response fields.
validateSearchResponseFields(fields);
// Retrieve the tag types.
List<TagTypeEntity> tagTypeEntities = tagTypeDao.getTagTypes();
// Build the list of tag types.
List<TagType> tagTypes = new ArrayList<>();
for (TagTypeEntity tagTypeEntity : tagTypeEntities)
{
tagTypes.add(createTagTypeFromEntity(tagTypeEntity, fields.contains(DISPLAY_NAME_FIELD), fields.contains(TAG_TYPE_ORDER_FIELD),
fields.contains(DESCRIPTION_FIELD)));
}
// Build and return the search response.
return new TagTypeSearchResponse(tagTypes);
}
@PublishJmsMessages
@Override
public TagType updateTagType(TagTypeKey tagTypeKey, TagTypeUpdateRequest request)
{
// Perform validation and trim.
tagTypeHelper.validateTagTypeKey(tagTypeKey);
// Perform validation and trim the alternate key parameters.
validateTagTypeUpdateRequest(request);
// Retrieve and ensure that a tag type already exists with the specified key.
TagTypeEntity tagTypeEntity = tagTypeDaoHelper.getTagTypeEntity(tagTypeKey);
// Validate the display name does not already exist for another tag type.
if (!StringUtils.equalsIgnoreCase(tagTypeEntity.getDisplayName(), request.getDisplayName()))
{
// Validate that the description is different.
tagTypeDaoHelper.assertTagTypeDisplayNameDoesNotExist(request.getDisplayName());
}
// Update and persist the tag type entity.
updateTagTypeEntity(tagTypeEntity, request);
// Notify the search index that a business object definition must be updated.
List<TagEntity> tagEntities = tagDao.getTagsByTagTypeEntityAndParentTagCode(tagTypeEntity, null, null);
searchIndexUpdateHelper.modifyBusinessObjectDefinitionsInSearchIndex(businessObjectDefinitionDao.getBusinessObjectDefinitions(tagEntities),
SEARCH_INDEX_UPDATE_TYPE_UPDATE);
// Notify the tag search index that tags must be updated.
searchIndexUpdateHelper.modifyTagsInSearchIndex(tagEntities, SEARCH_INDEX_UPDATE_TYPE_UPDATE);
// Create and return the tag type from the persisted entity.
return createTagTypeFromEntity(tagTypeEntity);
}
/**
* Creates and persists a new tag type entity.
*
* @param request the tag type create request
*
* @return the newly created tag type entity
*/
private TagTypeEntity createTagTypeEntity(TagTypeCreateRequest request)
{
TagTypeEntity tagTypeEntity = new TagTypeEntity();
tagTypeEntity.setCode(request.getTagTypeKey().getTagTypeCode());
tagTypeEntity.setDisplayName(request.getDisplayName());
tagTypeEntity.setOrderNumber(request.getTagTypeOrder());
tagTypeEntity.setDescription(request.getDescription());
return tagTypeDao.saveAndRefresh(tagTypeEntity);
}
/**
* Creates the tag type registration from the persisted entity.
*
* @param tagTypeEntity the tag type registration entity
*
* @return the tag type registration
*/
private TagType createTagTypeFromEntity(TagTypeEntity tagTypeEntity)
{
return createTagTypeFromEntity(tagTypeEntity, true, true, true);
}
/**
* Creates the tag type registration from the persisted entity.
*
* @param tagTypeEntity the tag type registration entity
* @param includeDisplayName specifies to include the display name field
* @param includeTagTypeOrder specifies to include the tag type order field
* @param includeDescription specifies to include the description field
*
* @return the tag type registration
*/
private TagType createTagTypeFromEntity(TagTypeEntity tagTypeEntity, boolean includeDisplayName, boolean includeTagTypeOrder, boolean includeDescription)
{
TagType tagType = new TagType();
TagTypeKey tagTypeKey = new TagTypeKey();
tagType.setTagTypeKey(tagTypeKey);
tagTypeKey.setTagTypeCode(tagTypeEntity.getCode());
if (includeDisplayName)
{
tagType.setDisplayName(tagTypeEntity.getDisplayName());
}
if (includeTagTypeOrder)
{
tagType.setTagTypeOrder(tagTypeEntity.getOrderNumber());
}
if (includeDescription)
{
tagType.setDescription(tagTypeEntity.getDescription());
}
return tagType;
}
/**
* Update and persist the tag type per specified update request.
*
* @param tagTypeEntity the tag type entity
* @param request the tag type update request
*/
private void updateTagTypeEntity(TagTypeEntity tagTypeEntity, TagTypeUpdateRequest request)
{
// Update the tag type entity fields.
tagTypeEntity.setDisplayName(request.getDisplayName());
tagTypeEntity.setOrderNumber(request.getTagTypeOrder());
tagTypeEntity.setDescription(request.getDescription());
// Persist and refresh the entity.
tagTypeDao.saveAndRefresh(tagTypeEntity);
}
/**
* Validates the tag type create request. This method also trims the request parameters.
*
* @param request the tag type create request
*/
private void validateTagTypeCreateRequest(TagTypeCreateRequest request)
{
Assert.notNull(request, "A tag type create request must be specified.");
tagTypeHelper.validateTagTypeKey(request.getTagTypeKey());
request.setDisplayName(alternateKeyHelper.validateStringParameter("display name", request.getDisplayName()));
Assert.notNull(request.getTagTypeOrder(), "A tag type order must be specified.");
}
/**
* Validates the tag type update request. This method also trims the request parameters.
*
* @param request the tag type update request
*/
private void validateTagTypeUpdateRequest(TagTypeUpdateRequest request)
{
Assert.notNull(request, "A tag type update request must be specified.");
request.setDisplayName(alternateKeyHelper.validateStringParameter("display name", request.getDisplayName()));
Assert.notNull(request.getTagTypeOrder(), "A tag type order must be specified.");
}
}