208 lines
10 KiB
Java
208 lines
10 KiB
Java
package eu.eudat.service.deposit;
|
|
|
|
import eu.eudat.authorization.Permission;
|
|
import eu.eudat.cache.deposit.RepositoryDepositConfigurationCache;
|
|
import eu.eudat.commons.enums.EntityType;
|
|
import eu.eudat.commons.enums.IsActive;
|
|
import eu.eudat.configurations.deposit.DepositProperties;
|
|
import eu.eudat.convention.ConventionService;
|
|
import eu.eudat.data.DmpEntity;
|
|
import eu.eudat.data.EntityDoiEntity;
|
|
import eu.eudat.data.old.DMP;
|
|
import eu.eudat.depositinterface.models.DMPDepositModel;
|
|
import eu.eudat.depositinterface.models.FileEnvelope;
|
|
import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration;
|
|
import eu.eudat.model.doi.DepositRequest;
|
|
import eu.eudat.model.doi.Doi;
|
|
import eu.eudat.model.doi.RepositoryConfig;
|
|
import eu.eudat.model.doi.RepositoryConfigs;
|
|
import eu.eudat.model.mapper.deposit.DmpEntityDepositMapper;
|
|
import eu.eudat.repository.DepositRepository;
|
|
import eu.eudat.utilities.pdf.PDFUtils;
|
|
import gr.cite.commons.web.authz.service.AuthorizationService;
|
|
import gr.cite.commons.web.oidc.apikey.ApiKeyCacheService;
|
|
import gr.cite.commons.web.oidc.apikey.webflux.ApiKeyExchangeFilterFunction;
|
|
import gr.cite.commons.web.oidc.apikey.webflux.ApiKeyWebfluxModel;
|
|
import jakarta.persistence.EntityManager;
|
|
import jakarta.persistence.NoResultException;
|
|
import jakarta.persistence.criteria.CriteriaBuilder;
|
|
import jakarta.persistence.criteria.CriteriaQuery;
|
|
import jakarta.persistence.criteria.Join;
|
|
import jakarta.persistence.criteria.Root;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.core.env.Environment;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.util.ResourceUtils;
|
|
import org.springframework.web.reactive.function.client.WebClient;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.net.URI;
|
|
import java.time.Instant;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.UUID;
|
|
|
|
@Service
|
|
public class RepositoryDepositService {
|
|
private static final Logger logger = LoggerFactory.getLogger(RepositoryDepositService.class);
|
|
|
|
private final DepositProperties depositProperties;
|
|
private final List<DepositRepository> clients;
|
|
private final ApiKeyCacheService apiKeyCacheService;
|
|
private final RepositoryDepositConfigurationCache repositoryDepositConfigurationCache;
|
|
private final EntityManager entityManager;
|
|
private final AuthorizationService authorizationService;
|
|
private final ConventionService conventionService;
|
|
private final Environment environment;
|
|
private final DmpEntityDepositMapper depositMapper;
|
|
|
|
@Autowired
|
|
public RepositoryDepositService(DepositProperties depositProperties, ApiKeyCacheService apiKeyCacheService, RepositoryDepositConfigurationCache repositoryDepositConfigurationCache, WebClient.Builder builder, EntityManager entityManager, AuthorizationService authorizationService, ConventionService conventionService, Environment environment, DmpEntityDepositMapper depositMapper) {
|
|
this.depositProperties = depositProperties;
|
|
this.apiKeyCacheService = apiKeyCacheService;
|
|
this.repositoryDepositConfigurationCache = repositoryDepositConfigurationCache;
|
|
this.clients = depositRepositories(builder);
|
|
this.entityManager = entityManager;
|
|
this.authorizationService = authorizationService;
|
|
this.conventionService = conventionService;
|
|
this.environment = environment;
|
|
this.depositMapper = depositMapper;
|
|
//GK: I don't like this but that way you can both cache the available configurations and set Configuration Ids for each client
|
|
getAvailableConfigurations();
|
|
}
|
|
|
|
|
|
public List<RepositoryConfig> getAvailableConfigurations() {
|
|
RepositoryConfigs configs = repositoryDepositConfigurationCache.lookup("base");
|
|
if (configs == null) {
|
|
List<RepositoryConfig> configurations = new ArrayList<>();
|
|
|
|
clients.forEach((client) -> {
|
|
List<RepositoryDepositConfiguration> repositoryConfigs = client.getConfiguration();
|
|
if (repositoryConfigs != null && !repositoryConfigs.isEmpty()) {
|
|
client.getConfigurationIds().addAll(repositoryConfigs.stream().map(RepositoryDepositConfiguration::getRepositoryId).toList());
|
|
configurations.addAll(repositoryConfigs.stream().map(RepositoryConfig::toModel).toList());
|
|
}
|
|
});
|
|
|
|
configs = new RepositoryConfigs(configurations);
|
|
this.repositoryDepositConfigurationCache.put("base", configs);
|
|
}
|
|
|
|
return configs.getRepositoryConfigs();
|
|
}
|
|
|
|
public Doi deposit(DepositRequest dmpDepositModel) {
|
|
this.authorizationService.authorize(Permission.EditDmp);
|
|
//GK: Why it is in that service, and why it's not static?
|
|
this.conventionService.isValidGuid(UUID.fromString(dmpDepositModel.getDmpId()));
|
|
//GK: First get the right client
|
|
DepositRepository repository = clients.stream().filter(client -> client.getConfigurationIds().contains(dmpDepositModel.getRepositoryId())).findFirst().orElseThrow();
|
|
//GK: Second get the Target Data Management Plan
|
|
DmpEntity dmpEntity = this.entityManager.find(DmpEntity.class, UUID.fromString(dmpDepositModel.getDmpId()));
|
|
|
|
//GK: Third get the DOI from the previous Data Management Plan (if it exists)
|
|
String previousDOI = null;
|
|
if (dmpEntity.getVersion() > 1) { //TODO: Will it start from 1 or 0?
|
|
previousDOI = this.getPreviousDOI(dmpEntity.getGroupId(), dmpEntity.getId(), dmpDepositModel.getRepositoryId());
|
|
}
|
|
|
|
//GK: Forth make the required files to be uploaded with the deposit
|
|
//TODO: Properly create required files
|
|
FileEnvelope docEnvelope = new FileEnvelope();
|
|
FileEnvelope pdfEnvelope = new FileEnvelope();
|
|
FileEnvelope jsonEnvelope = new FileEnvelope();
|
|
File zip = new File(environment.getProperty("temp.temp") + UUID.randomUUID() + ".zip");
|
|
try {
|
|
File documentFile = ResourceUtils.getFile(this.environment.getProperty("coniguration.h2020template"));
|
|
docEnvelope.setFilename("test.docx");
|
|
docEnvelope.setFile(documentFile);
|
|
File pdfFile = PDFUtils.convertToPDF(docEnvelope, environment);
|
|
pdfEnvelope.setFilename("test.pdf");
|
|
pdfEnvelope.setFile(pdfFile);
|
|
File jsonFile = new File(this.environment.getProperty("temp.temp") + UUID.randomUUID() + ".json");
|
|
jsonEnvelope.setFilename("test.json");
|
|
jsonEnvelope.setFile(jsonFile);
|
|
|
|
} catch (IOException e) {
|
|
logger.error(e.getMessage(), e);
|
|
}
|
|
|
|
//GK: Fifth Transform them to the DepositModel
|
|
DMPDepositModel depositModel = depositMapper.toDeposit(dmpEntity, zip, pdfEnvelope, jsonEnvelope, previousDOI);
|
|
|
|
//GK: Sixth Perform the deposit
|
|
String doi = "";
|
|
try {
|
|
doi = repository.deposit(dmpDepositModel.getRepositoryId(), depositModel, "");
|
|
} catch (Exception e) {
|
|
logger.error(e.getMessage(), e);
|
|
}
|
|
//GK: Something has gone wrong return null
|
|
if (doi.isEmpty())
|
|
return null;
|
|
//GK: doi is fine store it in database
|
|
EntityDoiEntity doiEntity = new EntityDoiEntity();
|
|
doiEntity.setId(UUID.randomUUID());
|
|
doiEntity.setDoi(doi);
|
|
doiEntity.setEntityType(EntityType.DMP);
|
|
DMP dmp = new DMP();
|
|
dmp.setId(dmpEntity.getId());
|
|
doiEntity.setEntityId(dmp);
|
|
doiEntity.setCreatedAt(Instant.now());
|
|
doiEntity.setIsActive(IsActive.Active);
|
|
entityManager.persist(doiEntity);
|
|
|
|
|
|
return Doi.fromDataModel(doiEntity);
|
|
}
|
|
|
|
private List<DepositRepository> depositRepositories(WebClient.Builder builder) {
|
|
List<DepositRepository> tclients = new ArrayList<>();
|
|
for (DepositProperties.DepositSource source: depositProperties.getSources()) {
|
|
|
|
String host = URI.create(source.getUrl()).getHost();
|
|
ApiKeyWebfluxModel apiKeyWebfluxModel = new ApiKeyWebfluxModel(host + "_" + source.getClientId(), source.getIssuerUrl(), source.getClientId(), source.getClientSecret(), source.getScope());
|
|
ApiKeyExchangeFilterFunction apiKeyExchangeFilterFunction = new ApiKeyExchangeFilterFunction(this.apiKeyCacheService, apiKeyWebfluxModel);
|
|
|
|
tclients.add(new DepositRepository(builder.baseUrl(source.getUrl() + "/api/deposit").filters(exchangeFilterFunctions -> exchangeFilterFunctions.add(apiKeyExchangeFilterFunction)).build()));
|
|
}
|
|
return tclients;
|
|
}
|
|
|
|
private String getPreviousDOI(UUID groupId, UUID currentId, String repoId) {
|
|
CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();
|
|
EntityDoiEntity doiEntity = null;
|
|
|
|
//GK: Step one get the previous version of the Data management plan
|
|
CriteriaQuery<DmpEntity> query = builder.createQuery(DmpEntity.class);
|
|
Root<DmpEntity> root = query.from(DmpEntity.class);
|
|
query = query.select(root.get("id"));
|
|
query = query.where(builder.and(builder.equal(root.get("groupId"), groupId), builder.equal(root.get("isActive"), IsActive.Active)));
|
|
query = query.orderBy(builder.desc(root.get("version")));
|
|
List<UUID> dmpIds = this.entityManager.createQuery(query).getResultList().stream().map(DmpEntity::getId).toList();
|
|
|
|
//GK: Step two get it's doiEntity
|
|
CriteriaQuery<EntityDoiEntity> doiQuery = builder.createQuery(EntityDoiEntity.class);
|
|
Root<EntityDoiEntity> doiRoot = doiQuery.from(EntityDoiEntity.class);
|
|
doiQuery = doiQuery.multiselect(doiRoot.get("entityId").get("id"), doiRoot.get("doi"));
|
|
doiQuery = doiQuery.where(builder.and(doiRoot.get("entityId").get("id").in(dmpIds), builder.equal(doiRoot.get("isActive"), IsActive.Active), builder.equal(doiRoot.get("repositoryId"), repoId)));
|
|
List<EntityDoiEntity> dois = this.entityManager.createQuery(doiQuery).getResultList();
|
|
|
|
for(UUID uuid: dmpIds)
|
|
{
|
|
if (uuid.equals(currentId))
|
|
continue;
|
|
doiEntity = dois.stream()
|
|
.filter(entityDoiEntity -> entityDoiEntity.getEntityId().getId().equals(uuid)).findFirst().orElse(null);
|
|
if (doiEntity != null)
|
|
break;
|
|
}
|
|
return doiEntity != null ? doiEntity.getDoi() : null;
|
|
}
|
|
|
|
}
|