Skip to content
CopyService.java 3.67 KiB
Newer Older
/*
 * This file is part of vospace-rest
 * Copyright (C) 2021 Istituto Nazionale di Astrofisica
 * SPDX-License-Identifier: GPL-3.0-or-later
 */
package it.inaf.oats.vospace;

import it.inaf.ia2.aa.data.User;
import it.inaf.oats.vospace.datamodel.NodeUtils;
import it.inaf.oats.vospace.exception.InvalidArgumentException;
import it.inaf.oats.vospace.exception.NodeBusyException;
import it.inaf.oats.vospace.persistence.NodeDAO.ShortNodeDescriptor;
import java.util.List;
import java.util.Optional;
import net.ivoa.xml.vospace.v2.Transfer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.CannotSerializeTransactionException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

@Service
@EnableTransactionManagement
public class CopyService extends AbstractNodeService {

    @Autowired
    private NodeBranchService nodeBranchService;

    @Transactional(rollbackFor = {Exception.class}, isolation = Isolation.REPEATABLE_READ)
    public List<String> processCopyNodes(Transfer transfer, String jobId, User user) {
        if (transfer.getTarget().size() != 1) {
            throw new InvalidArgumentException("Invalid target size for copyNode: " + transfer.getTarget().size());
        }

        // Get Source Vos Path
        String sourcePath = URIUtils.returnVosPathFromNodeURI(transfer.getTarget().get(0), authority);

        // Get Destination Vos Path (it's in transfer direction)
        String destinationPath = URIUtils.returnVosPathFromNodeURI(transfer.getDirection(), authority);

        this.validatePath(sourcePath);
        this.validatePath(destinationPath);

        if (sourcePath.equals(destinationPath)) {
        List<String> copiedNodesPaths = null;
        try {

            // check source branch for read and lock it
Nicola Fulvio Calabria's avatar
Nicola Fulvio Calabria committed
            nodeBranchService.checkBranchForReadAndLock(sourcePath, jobId, user);

            // Check destination
            Optional<ShortNodeDescriptor> destShortNodeDescriptor
                    = nodeDao.getShortNodeDescriptor(destinationPath, user.getName(), user.getGroups());

            if (destShortNodeDescriptor.isPresent()) {
                this.validateDestinationContainer(destShortNodeDescriptor.get(), destinationPath);
                copiedNodesPaths = nodeDao.copyBranch(
                        sourcePath,
                        destinationPath + "/" + NodeUtils.getNodeName(sourcePath),
                        jobId);

            } else {
                // Check if parent exists
                String destinationParentPath = NodeUtils.getParentPath(destinationPath);
                Optional<ShortNodeDescriptor> destShortNodeDescriptorParent
                        = nodeDao.getShortNodeDescriptor(destinationParentPath, user.getName(), user.getGroups());
                if (destShortNodeDescriptorParent.isPresent()) {
                    this.validateDestinationContainer(destShortNodeDescriptorParent.get(), destinationParentPath);
                    copiedNodesPaths = nodeDao.copyBranch(sourcePath,
                            destinationPath, jobId);

                } else {
                    throw new UnsupportedOperationException("Creation of destination upon copy not supported");
                }

            }

        } catch (CannotSerializeTransactionException ex) {
            // Concurrent transactions attempted to modify this set of nodes            
            throw new NodeBusyException(sourcePath);
        }