DescriptorListServiceImpl.java
/*
* Copyright 2018 Global Crop Diversity Trust
*
* 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.genesys.server.service.impl;
import static org.genesys.server.model.traits.QDescriptorList.descriptorList;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.genesys.blocks.security.model.AclSid;
import org.genesys.blocks.security.serialization.Permissions;
import org.genesys.blocks.security.service.CustomAclService;
import org.genesys.server.component.aspect.NotifyForReview;
import org.genesys.server.component.aspect.NotifyOnPublished;
import org.genesys.server.component.security.SecurityUtils;
import org.genesys.server.exception.InvalidApiUsageException;
import org.genesys.server.exception.NotFoundElement;
import org.genesys.server.exception.SearchException;
import org.genesys.server.model.Partner;
import org.genesys.server.model.PublishState;
import org.genesys.server.model.UserRole;
import org.genesys.server.model.filters.DescriptorListFilter;
import org.genesys.server.model.traits.Descriptor;
import org.genesys.server.model.traits.DescriptorList;
import org.genesys.server.model.traits.DescriptorListLang;
import org.genesys.server.persistence.DescriptorListLangRepository;
import org.genesys.server.persistence.traits.DescriptorListRepository;
import org.genesys.server.service.DescriptorListService;
import org.genesys.server.service.DescriptorListTranslationService;
import org.genesys.server.service.DescriptorService;
import org.genesys.server.service.DescriptorTranslationService;
import org.genesys.server.service.DownloadService;
import org.genesys.server.service.ElasticsearchService;
import org.genesys.server.service.TranslatorService;
import org.genesys.server.service.TranslatorService.FormattedText;
import org.genesys.server.service.TranslatorService.TextFormat;
import org.genesys.util.JPAUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import com.google.common.collect.Sets;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Predicate;
/**
* Service for working with {@link DescriptorList}.
*
* @author Andrey Lugovskoy
*/
@Slf4j
@Service
@Transactional(readOnly = true)
@Validated
public class DescriptorListServiceImpl extends FilteredTranslatedCRUDServiceImpl<
DescriptorList, DescriptorListLang, DescriptorListTranslationService.TranslatedDescriptorList, DescriptorListFilter, DescriptorListRepository>
implements DescriptorListService {
@Autowired
private DescriptorListRepository descriptorListRepository;
/** The securityUtils. */
@Autowired
private SecurityUtils securityUtils;
@Autowired
private DescriptorService descriptorService;
@Autowired
private DownloadService downloadService;
@Autowired(required = false)
private ElasticsearchService elasticsearchService;
@Autowired
private CustomAclService aclService;
@Autowired(required = false)
private TranslatorService translatorService;
@Autowired
DescriptorTranslationService descriptorTranslationService;
@Component(value = "DescriptorListTranslationSupport")
protected static class DescriptorListTranslationSupport
extends BaseTranslationSupport<
DescriptorList, DescriptorListLang, DescriptorListTranslationService.TranslatedDescriptorList, DescriptorListFilter, DescriptorListLangRepository>
implements DescriptorListTranslationService {
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#source.entity, 'ADMINISTRATION')")
public DescriptorListLang create(DescriptorListLang source) {
return super.create(source);
}
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#target.entity, 'ADMINISTRATION')")
public DescriptorListLang update(DescriptorListLang updated, DescriptorListLang target) {
return super.update(updated, target);
}
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#source.entity, 'ADMINISTRATION')")
public DescriptorListLang remove(DescriptorListLang source) {
return super.remove(source);
}
}
@Override
@PostAuthorize("returnObject == null || returnObject.isPublished() || hasRole('ADMINISTRATOR') || hasPermission(returnObject, 'read')")
public DescriptorList get(UUID uuid) {
return repository.findByUuid(uuid);
}
@Override
public long countDescriptorLists(DescriptorListFilter filter) throws SearchException {
if (filter.isFulltextQuery()) {
return elasticsearchService.count(DescriptorList.class, filter);
}
return descriptorListRepository.count(filter.buildPredicate());
}
private DescriptorList getDescriptorList(final DescriptorList input) {
final DescriptorList descriptorList = descriptorListRepository.findById(input.getId()).orElse(null);
if (descriptorList == null) {
throw new NotFoundElement("Record not found by id=" + input.getId());
}
if (!descriptorList.getVersion().equals(input.getVersion())) {
log.warn("Subset versions don't match anymore");
throw new ConcurrencyFailureException("Object version changed to " + descriptorList.getVersion() + ", you provided " + input.getVersion());
}
return descriptorList;
}
private DescriptorList getUnpublishedDescriptorList(final DescriptorList input) {
DescriptorList loadedDescriptorList = getDescriptorList(input);
if (loadedDescriptorList.isPublished()) {
throw new InvalidApiUsageException("Cannot modify a published Descriptor List.");
}
return loadedDescriptorList;
}
/**
* {@inheritDoc}
*/
@Transactional
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#input.owner, 'write')")
public DescriptorList create(final DescriptorList input) {
return createFast(input);
}
@Override
@Transactional
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#input.owner, 'write')")
public DescriptorList createFast(DescriptorList input) {
log.info("Create descriptor list {}", input);
final DescriptorList descriptorList = new DescriptorList();
copyValues(descriptorList, input);
descriptorList.setOwner(input.getOwner());
// can not be published when creating
descriptorList.setState(PublishState.DRAFT);
final DescriptorList saved = descriptorListRepository.save(descriptorList);
// Grant all permissions to the Partner's SID
final AclSid sid = aclService.ensureAuthoritySid(saved.getOwner().getAuthorityName());
aclService.setPermissions(saved, sid, new Permissions().grantAll());
return saved;
}
/**
* {@inheritDoc}
*/
@Override
@Transactional
@PreAuthorize("hasRole('ADMINISTRATOR') or (! #input.isPublished() and hasPermission(#input, 'write'))")
public DescriptorList update(final DescriptorList input) {
final DescriptorList descriptorList = getUnpublishedDescriptorList(input);
return update(input, descriptorList);
}
@Override
@Transactional
@PreAuthorize("hasRole('ADMINISTRATOR') or (! #target.isPublished() and hasPermission(#target, 'write'))")
public DescriptorList update(DescriptorList updated, DescriptorList target) {
return lazyLoad(updateFast(updated, target));
}
@Override
@Transactional
@PreAuthorize("hasRole('ADMINISTRATOR') or (! #target.isPublished() and hasPermission(#target, 'write'))")
public DescriptorList updateFast(DescriptorList updated, DescriptorList target) {
log.info("Updating descriptor list {}", updated);
if (updated.getOwner() != null && !target.getOwner().equals(updated.getOwner())) {
throw new InvalidApiUsageException("Descriptor list owner can't be changed");
}
copyValues(target, updated);
return descriptorListRepository.save(target);
}
@Override
@Transactional
@PreAuthorize("hasRole('ADMINISTRATOR') or (! #descriptorList.isPublished() and hasPermission(#descriptorList, 'DELETE'))")
public DescriptorList remove(DescriptorList descriptorList) {
descriptorList = getUnpublishedDescriptorList(descriptorList);
descriptorListRepository.delete(descriptorList);
return descriptorList;
}
/**
* {@inheritDoc}
*/
@Transactional
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') or (! #descriptorList.isPublished() and hasPermission(#descriptorList, 'WRITE'))")
public DescriptorList removeDescriptors(final DescriptorList descriptorList, final Descriptor... descriptors) {
final DescriptorList loaded = getUnpublishedDescriptorList(descriptorList);
log.info("Remove descriptors {} of descriptor list{}.", descriptors, descriptorList);
if (descriptors == null || descriptors.length == 0) {
// Noop
return descriptorList;
}
// Which UUIDs to remove?
final Set<UUID> descriptorUuids = Arrays.stream(descriptors).map(descriptor -> descriptor.getUuid()).collect(Collectors.toSet());
// Keep descriptors that are not in the list
loaded.setDescriptors(loaded.getDescriptors().stream().filter(descriptor -> !descriptorUuids.contains(descriptor.getUuid())).collect(Collectors.toList()));
return lazyLoad(descriptorListRepository.save(loaded));
}
/**
* {@inheritDoc}
*/
@Transactional
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') or (! #descriptorList.isPublished() and hasPermission(#descriptorList, 'WRITE'))")
public DescriptorList addDescriptors(final DescriptorList descriptorList, final Descriptor... descriptors) {
final DescriptorList loaded = getUnpublishedDescriptorList(descriptorList);
if (descriptors == null || descriptors.length == 0) {
// Noop
return descriptorList;
}
// append to end
for (final Descriptor descriptor : descriptors) {
if (loaded.getDescriptors().contains(descriptor)) {
log.info("Not adding existing descriptor uuid={} title={} to descriptionList uuid={} title={}", descriptor.getUuid(), descriptor.getTitle(), descriptorList.getUuid(), descriptorList
.getTitle());
} else {
log.info("Add descriptor uuid={} title={} to descriptionList uuid={} title={}", descriptor.getUuid(), descriptor.getTitle(), descriptorList.getUuid(), descriptorList
.getTitle());
loaded.getDescriptors().add(descriptor);
}
}
return lazyLoad(descriptorListRepository.save(loaded));
}
/**
* {@inheritDoc}
*/
@Transactional
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') or (! #descriptorList.isPublished() and hasPermission(#descriptorList, 'WRITE'))")
public DescriptorList setDescriptors(final DescriptorList descriptorList, final Descriptor[] descriptors) {
final DescriptorList loaded = getUnpublishedDescriptorList(descriptorList);
if (descriptors == null || descriptors.length == 0) {
// Noop
return descriptorList;
}
// Re-add them in order
loaded.getDescriptors().clear();
for (final Descriptor descriptor : descriptors) {
log.info("Add descriptor uuid={} title={} to descriptionList uuid={} title={}", descriptor.getUuid(), descriptor.getTitle(), descriptorList.getUuid(), descriptorList
.getTitle());
loaded.getDescriptors().add(descriptor);
}
return lazyLoad(descriptorListRepository.save(loaded));
}
private DescriptorList lazyLoad(final DescriptorList descriptorList) {
if (descriptorList == null) {
throw new NotFoundElement("No such descriptor list");
}
if (descriptorList.getOwner() != null) {
descriptorList.getOwner().getId();
}
return descriptorList;
}
private List<Descriptor> lazyLoadDescriptors(List<Descriptor> descriptors) {
if (descriptors != null) {
descriptors.size();
descriptors.forEach(descriptor -> {
descriptor.getTerms().size();
if (descriptor.getImage() != null) {
descriptor.getImage().getId();
}
});
}
return descriptors;
}
@Override
@PostAuthorize("hasRole('ADMINISTRATOR') || returnObject==null || returnObject.isPublished() || hasPermission(returnObject, 'read')")
public DescriptorList load(final long id) {
return lazyLoad(descriptorListRepository.findById(id).orElse(null));
}
@Override
@PostAuthorize("hasRole('ADMINISTRATOR') || returnObject==null || returnObject.isPublished() || hasPermission(returnObject, 'read')")
public DescriptorList loadDescriptorList(final UUID uuid) {
return lazyLoad(descriptorListRepository.findByUuid(uuid));
}
@Override
@PostAuthorize("hasRole('ADMINISTRATOR') || returnObject==null || returnObject.entity.isPublished() || hasPermission(returnObject.entity, 'read')")
public DescriptorListTranslationService.TranslatedDescriptorList loadTranslatedDescriptorList(final UUID uuid) {
return translate(lazyLoad(descriptorListRepository.findByUuid(uuid)));
}
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') || #descriptorList.isPublished() || hasPermission(#descriptorList, 'read')")
public List<Descriptor> loadDescriptors(DescriptorList descriptorList) {
descriptorList = descriptorListRepository.findByUuid(descriptorList.getUuid());
return lazyLoadDescriptors(descriptorList.getDescriptors());
}
@Override
@PostAuthorize("hasRole('ADMINISTRATOR') || returnObject==null || returnObject.isPublished() || hasPermission(returnObject, 'read')")
public DescriptorList loadDescriptorList(final UUID uuid, final int version) {
return lazyLoad(descriptorListRepository.findByUuidAndVersion(uuid, version));
}
/**
* {@inheritDoc}
*/
private void copyValues(final DescriptorList target, final DescriptorList source) {
// do not copy source#owner
target.setCrop(source.getCrop());
target.setDescription(source.getDescription());
target.setState(source.getState());
target.setTitle(source.getTitle());
target.setUrl(source.getUrl());
target.setVersionTag(source.getVersionTag());
target.setUuid(source.getUuid());
target.setBibliographicCitation(source.getBibliographicCitation());
target.setPublisher(source.getPublisher());
target.setOriginalLanguageTag(source.getOriginalLanguageTag());
}
@Override
@PostAuthorize("hasRole('ADMINISTRATOR') || returnObject==null || returnObject.isPublished() || hasPermission(returnObject, 'read')")
public DescriptorList loadDescriptorList(final DescriptorList input) {
return loadDescriptorList(input.getUuid(), input.getVersion());
}
private DescriptorList loadDescriptorList(final UUID uuid, final Integer version) {
if (uuid == null) {
throw new InvalidApiUsageException("Required parameter uuid is missing");
}
final DescriptorList descriptorList = descriptorListRepository.findByUuid(uuid);
if (descriptorList == null) {
throw new NotFoundElement("Record not found by uuid=" + uuid);
}
if (version != null && !descriptorList.getVersion().equals(version)) {
throw new ConcurrencyFailureException("Object version changed to " + descriptorList.getVersion() + ", you provided " + version);
}
return descriptorList;
}
@Override
public Page<DescriptorList> list(final DescriptorListFilter filters, final Pageable page) throws SearchException {
final BooleanBuilder published = new BooleanBuilder();
published.and(descriptorList.state.in(PublishState.PUBLISHED));
if (filters.isFulltextQuery()) {
return elasticsearchService.findAll(DescriptorList.class, filters, published, page);
}
Pageable markdownSortPageRequest = JPAUtils.toMarkdownSort(page, "title");
Page<DescriptorList> res = descriptorListRepository.findAll(published.and(filters.buildPredicate()), markdownSortPageRequest);
return new PageImpl<DescriptorList>(res.getContent(), page, res.getTotalElements());
}
@Override
public Page<DescriptorListTranslationService.TranslatedDescriptorList> listFiltered(final DescriptorListFilter filters, final Pageable page) throws SearchException {
final BooleanBuilder published = new BooleanBuilder();
published.and(descriptorList.state.in(PublishState.PUBLISHED));
Page<DescriptorList> res;
if (filters.isFulltextQuery()) {
res = elasticsearchService.findAll(DescriptorList.class, filters, published, page);
} else {
Pageable markdownSortPageRequest = JPAUtils.toMarkdownSort(page, "title");
res = descriptorListRepository.findAll(published.and(filters.buildPredicate()), markdownSortPageRequest);
}
return new PageImpl<>(translationSupport.getTranslated(res.getContent()), page, res.getTotalElements());
}
/**
* {@inheritDoc}
*/
@Override
public Map<String, ElasticsearchService.TermResult> getSuggestions(DescriptorListFilter filter) throws SearchException, IOException {
assert (filter != null);
Set<String> suggestions = Sets.newHashSet("crop");
Map<String, ElasticsearchService.TermResult> suggestionRes = new HashMap<>(suggestions.size());
for (String suggestionKey : suggestions) {
DescriptorListFilter suggestionFilter = filter.copy(DescriptorListFilter.class);
suggestionFilter.state(PublishState.PUBLISHED);
try {
suggestionFilter.clearFilter(suggestionKey);
} catch (NoSuchFieldException | IllegalAccessException e) {
log.error("Error while clearing filter: ", e.getMessage());
}
ElasticsearchService.TermResult suggestion = elasticsearchService.termStatisticsAuto(DescriptorList.class, suggestionFilter, 100, suggestionKey);
suggestionRes.put(suggestionKey, suggestion);
}
return suggestionRes;
}
@Override
public Page<DescriptorList> listDescriptorListsForCurrentUser(final DescriptorListFilter filter, final Pageable page) throws SearchException {
final Pageable markdownSortPageRequest = JPAUtils.toMarkdownSort(page, "title");
Page<DescriptorList> res;
if (securityUtils.hasRole(UserRole.ADMINISTRATOR)) {
if (filter.isFulltextQuery()) {
res = elasticsearchService.findAll(DescriptorList.class, filter, markdownSortPageRequest);
} else {
res = descriptorListRepository.findAll(filter.buildPredicate(), markdownSortPageRequest);
}
} else {
final HashSet<Long> partners = new HashSet<>(securityUtils.listObjectIdentityIdsForCurrentUser(Partner.class, BasePermission.WRITE));
if (filter.isFulltextQuery()) {
res = elasticsearchService.findAll(DescriptorList.class, filter, descriptorList.owner().id.in(partners), markdownSortPageRequest);
} else {
res = descriptorListRepository.findAll(descriptorList.owner().id.in(partners).and(filter.buildPredicate()), markdownSortPageRequest);
}
}
return new PageImpl<DescriptorList>(res.getContent(), page, res.getTotalElements());
}
/**
* {@inheritDoc}
*/
@Override
@Transactional
@PreAuthorize("hasRole('ADMINISTRATOR')")
@NotifyOnPublished
public DescriptorList approveDescriptorList(final DescriptorList descriptorList) {
final DescriptorList loaded = getUnpublishedDescriptorList(descriptorList);
if (loaded.getState() == PublishState.DRAFT) {
throw new InvalidApiUsageException("Descriptor List should be sent for review before publication");
}
for (final Descriptor descriptor : loaded.getDescriptors()) {
if (descriptor.getState() != PublishState.PUBLISHED) {
log.info("Publishing descriptor {}", descriptor);
try {
descriptorService.approveDescriptor(descriptor);
} catch (InvalidApiUsageException e) {
throw e;
}
}
}
loaded.setState(PublishState.PUBLISHED);
return lazyLoad(descriptorListRepository.saveAndFlush(loaded));
}
/**
* {@inheritDoc}
*/
@Override
@Transactional
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#descriptorList, 'WRITE')")
@NotifyForReview
public DescriptorList reviewDescriptorList(final DescriptorList descriptorList) {
final DescriptorList loaded = getUnpublishedDescriptorList(descriptorList);
if (loaded.getState() == PublishState.REVIEWING) {
throw new InvalidApiUsageException("The DescriptorList is already under approval");
}
for (final Descriptor descriptor : loaded.getDescriptors()) {
if (descriptor.getState() == PublishState.DRAFT) {
log.info("Send to review descriptor {}", descriptor);
try {
descriptorService.reviewDescriptor(descriptor);
} catch (InvalidApiUsageException e) {
throw e;
}
}
}
loaded.setState(PublishState.REVIEWING);
return lazyLoad(descriptorListRepository.save(loaded));
}
/**
* {@inheritDoc}
*/
@Override
@Transactional
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#descriptorList, 'administration')")
public DescriptorList rejectDescriptorList(final DescriptorList descriptorList) {
final DescriptorList loaded = descriptorListRepository.findByUuidAndVersion(descriptorList.getUuid(), descriptorList.getVersion());
if (loaded == null) {
throw new NotFoundElement("No DescriptorList with specified uuid and version");
}
if (loaded.isPublished() && !securityUtils.hasRole(UserRole.ADMINISTRATOR)) {
long oneDay = 24 * 60 * 60 * 1000;
if (loaded.getLastModifiedDate() != null && loaded.getLastModifiedDate().toEpochMilli() <= (System.currentTimeMillis() - oneDay)) {
throw new InvalidApiUsageException("Cannot be un-published. More than 24 hours have passed since the publication.");
}
}
loaded.setState(PublishState.DRAFT);
descriptorListRepository.save(loaded);
for (final Descriptor referencedDescriptor : loaded.getDescriptors()) {
log.info("Rejecting descriptor {}", referencedDescriptor);
try {
descriptorService.rejectDescriptor(referencedDescriptor);
} catch (final InvalidApiUsageException e) {
log.info("Not unpublishing a descriptor referenced in a published dataset or descriptor list: {}", e.getMessage());
}
}
return lazyLoad(descriptorListRepository.save(loaded));
}
/**
* {@inheritDoc}
*/
@Override
public List<DescriptorList> autocompleteDescriptorLists(final String text) {
Pageable markdownSortPageRequest = JPAUtils.toMarkdownSort(PageRequest.of(0, 15, Sort.by("title")), "title");
if (StringUtils.isBlank(text)) {
final Predicate predicate = descriptorList.state.in(PublishState.PUBLISHED);
return descriptorListRepository.findAll(predicate, markdownSortPageRequest).getContent();
} else {
final Predicate predicate = descriptorList.state.in(PublishState.PUBLISHED).and(descriptorList.title.containsIgnoreCase(text));
return descriptorListRepository.findAll(predicate, markdownSortPageRequest).getContent();
}
}
/**
* {@inheritDoc}
*/
@Override
@PreAuthorize("#descriptorList.isPublished() || hasRole('ADMINISTRATOR') || hasPermission(#descriptorList, 'read')")
public void exportDescriptorList(final DescriptorList descriptorList, final OutputStream outputStream) throws IOException {
downloadService.writeXlsxDescriptorList(descriptorListRepository.getReferenceById(descriptorList.getId()), outputStream);
}
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') || hasPermission(#original, 'write')")
public DescriptorListLang machineTranslate(DescriptorList original, String targetLanguage) throws TranslatorService.TranslatorException {
if (Objects.equals(original.getOriginalLanguageTag(), targetLanguage)) {
throw new InvalidApiUsageException("Source and target language are the same");
}
var mt = new DescriptorListLang();
mt.setMachineTranslated(true);
mt.setLanguageTag(targetLanguage);
mt.setEntity(original);
if (translatorService == null) return mt;
var builder = TranslatorService.TranslationStructuredRequest.builder()
.targetLang(targetLanguage);
// Translations to other languages use the English version (either original or translated)
if (! Objects.equals(Locale.ENGLISH.getLanguage(), targetLanguage) && ! Objects.equals(Locale.ENGLISH.getLanguage(), original.getOriginalLanguageTag())) {
var enTranslation = translationSupport.getLang(original, Locale.ENGLISH.getLanguage());
if (enTranslation == null) {
throw new InvalidApiUsageException("English text is not available.");
}
builder
.sourceLang(enTranslation.getLanguageTag())
// .context(enTranslation.getDescription())
.texts(Map.of(
"title", new FormattedText(TextFormat.markdown, enTranslation.getTitle()),
"description", new FormattedText(TextFormat.markdown, enTranslation.getDescription())
));
} else {
// Translations to English use the original texts
builder
.sourceLang(original.getOriginalLanguageTag())
// .context(original.getDescription())
.texts(Map.of(
"title", new FormattedText(TextFormat.markdown, original.getTitle()),
"description", new FormattedText(TextFormat.markdown, original.getDescription())
));
}
var translations = translatorService.translate(builder.build());
if (StringUtils.isNotBlank(original.getTitle())) {
mt.setTitle(translations.getTexts().get("title"));
}
if (StringUtils.isNotBlank(original.getDescription())) {
mt.setDescription(translations.getTexts().get("description"));
}
return mt;
}
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') || #descriptorList.isPublished() || hasPermission(#descriptorList, 'read')")
public List<DescriptorTranslationService.TranslatedDescriptor> loadTranslatedDescriptors(DescriptorList descriptorList) {
var reloaded = descriptorListRepository.findById(descriptorList.getId()).orElseThrow();
return descriptorTranslationService.getTranslated(reloaded.getDescriptors());
}
}