Commit e37671ea authored by Nicola Fulvio Calabria's avatar Nicola Fulvio Calabria
Browse files

Task #3603 completed

parent dd18567a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ public class JobService {
    @Autowired
    private TapeService tapeService;

    enum JobType {
    public enum JobType {
        pullToVoSpace,
        pullFromVoSpace,
        pushToVoSpace,
+40 −0
Original line number Diff line number Diff line
@@ -7,6 +7,8 @@ import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import net.ivoa.xml.uws.v1.ExecutionPhase;
import net.ivoa.xml.uws.v1.JobSummary;
import net.ivoa.xml.uws.v1.Jobs;
import net.ivoa.xml.uws.v1.ShortJobDescription;
import net.ivoa.xml.vospace.v2.Transfer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
@@ -19,6 +21,9 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import java.util.List;

@RestController
public class TransferController {
@@ -103,6 +108,41 @@ public class TransferController {
        return ResponseEntity.ok(jobDAO.getJob(jobId).get().getPhase().toString());
    }

    @GetMapping(value = "/transfers", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
    public ResponseEntity<?> getTransfers(
            @RequestParam(value = "PHASE", required = false) Optional<List<ExecutionPhase>> phase,
            @RequestParam(value = "AFTER", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Optional<LocalDateTime> after,
            @RequestParam(value = "LAST", required = false) Optional<Integer> last,
            @RequestParam(value = "direction", required = false) Optional<List<JobService.JobType>> direction,
            User principal) {        
        
        if(last.isPresent())
        {
            if(last.get() <= 0) 
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
        }

        String userId = principal.getName();

        List<ExecutionPhase> phaseList;
        if (phase.isPresent()) {
            phaseList = phase.get();
        } else {
            phaseList = List.of();
        }

        List<JobService.JobType> directionList;
        if (direction.isPresent()) {
            directionList = direction.get();
        } else {
            directionList = List.of();
        }       

        Jobs jobs = jobDAO.getJobs(userId, phaseList, directionList, after, last);

        return ResponseEntity.ok(jobs);
    }

    private JobSummary newJobSummary(Transfer transfer, User principal) {
        String jobId = UUID.randomUUID().toString().replace("-", "");

+133 −0
Original line number Diff line number Diff line
@@ -3,19 +3,29 @@ package it.inaf.oats.vospace.persistence;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.sql.Timestamp;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;
import java.util.Optional;
import javax.sql.DataSource;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import net.ivoa.xml.uws.v1.ExecutionPhase;
import net.ivoa.xml.uws.v1.JobSummary;
import net.ivoa.xml.uws.v1.ShortJobDescription;
import net.ivoa.xml.uws.v1.ResultReference;
import net.ivoa.xml.uws.v1.Jobs;
import it.inaf.oats.vospace.JobService;
import net.ivoa.xml.vospace.v2.Transfer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.time.LocalDateTime;
import java.math.BigDecimal;


@Repository
public class JobDAO {
@@ -105,6 +115,106 @@ public class JobDAO {
        return jobSummary;
    }

    public Jobs getJobs(String userId,
            List<ExecutionPhase> phaseList,
            List<JobService.JobType> directionList,
            Optional<LocalDateTime> after,
            Optional<Integer> last
    ) {
        Jobs jobs = new Jobs();
        jobs.setVersion("1.1");

        List<ShortJobDescription> sjdList = jobs.getJobref();
        // Query db to fill ShortJobDescription list
        ArrayList<Object> queryParams = new ArrayList<>();
        ArrayList<Integer> queryParamTypes = new ArrayList<>();

        StringBuilder sb = new StringBuilder();
        sb.append("SELECT * FROM job");

        sb.append(" WHERE owner_id = ?");
        queryParams.add(userId);
        queryParamTypes.add(Types.VARCHAR);

        // Fill conditions on execution phase
        if (phaseList.isEmpty()) {
            sb.append(" AND phase NOT IN (?)");
            queryParams.add(ExecutionPhase.ARCHIVED);
            queryParamTypes.add(Types.OTHER);
        } else {
            sb.append(" AND phase IN (");            
            for (int i = 0; i < phaseList.size(); i++) {
                sb.append("?");                
                queryParams.add(phaseList.get(i));
                queryParamTypes.add(Types.OTHER);
                if (i < phaseList.size() - 1) {
                    sb.append(",");
                }
            }
            sb.append(")");
        }

        // Fill conditions on type list
        if (!directionList.isEmpty()) {
            sb.append(" AND job_type IN (");
            for (int i = 0; i < directionList.size(); i++) {
                sb.append("?");
                queryParams.add(directionList.get(i));
                queryParamTypes.add(Types.OTHER);
                if (i < directionList.size() - 1) {
                    sb.append(",");
                }
            }
            sb.append(")");
        }

        // Fill conditions on creation date
        if (after.isPresent()) {
            sb.append(" AND creation_time > ?");
            queryParams.add(after.get());
            queryParamTypes.add(Types.TIMESTAMP);
        }

        sb.append(" ORDER BY creation_time DESC");

        if (last.isPresent()) {
            sb.append(" LIMIT ?");
            //sb.append(last.get().toString());
            queryParams.add(last.get());
            queryParamTypes.add(Types.INTEGER);
        }

        String sql = sb.toString();

        // Perform query
        jdbcTemplate.query(sql,
                (ps) -> {                    
                    for (int i = 0; i < queryParams.size(); i++) {
                        ps.setObject(i + 1, queryParams.get(i),
                                queryParamTypes.get(i));
                    }
                },
                (rs) -> {                    
                    sjdList.add(getShortJobDescriptionFromCurrentRow(rs));                    
                }
        );

        return jobs;
    }

    private ShortJobDescription getShortJobDescriptionFromCurrentRow(ResultSet rs)
            throws SQLException {
        ShortJobDescription sjd = new ShortJobDescription();
        sjd.setId(rs.getString("job_id"));
        sjd.setOwnerId(rs.getString("owner_id"));
        sjd.setType(rs.getString("job_type"));
        sjd.setPhase(ExecutionPhase.fromValue(rs.getString("phase")));
        sjd.setCreationTime(
                toXMLGregorianCalendar(rs.getTimestamp("creation_time")));        
        
        return sjd;
    }

    private Object getJobPayload(String jobType, String json) {
        try {
            // TODO: switch on jobType
@@ -145,4 +255,27 @@ public class JobDAO {
            throw new RuntimeException(ex);
        }
    }
    
    public static XMLGregorianCalendar toXMLGregorianCalendar(Timestamp t)
    {
        XMLGregorianCalendar cal = null;
        try{         
            cal = DatatypeFactory.newInstance().newXMLGregorianCalendar();
        
        LocalDateTime ldt = t.toLocalDateTime();
        
        cal.setYear(ldt.getYear());
        cal.setMonth(ldt.getMonthValue());
        cal.setDay(ldt.getDayOfMonth());
        cal.setHour(ldt.getHour());
        cal.setMinute(ldt.getMinute());
        cal.setSecond(ldt.getSecond());
        cal.setFractionalSecond(new BigDecimal("0." + ldt.getNano()));
                
        } catch(Exception e) {
           e.printStackTrace();
        }
        
        return cal;       
    }
}
+51 −1
Original line number Diff line number Diff line
@@ -6,9 +6,13 @@ import it.inaf.oats.vospace.persistence.JobDAO;
import it.inaf.oats.vospace.persistence.NodeDAO;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.Optional;
import net.ivoa.xml.uws.v1.ExecutionPhase;
import net.ivoa.xml.uws.v1.JobSummary;
import net.ivoa.xml.uws.v1.Jobs;
import net.ivoa.xml.uws.v1.ShortJobDescription;
import net.ivoa.xml.vospace.v2.DataNode;
import net.ivoa.xml.vospace.v2.Node;
import net.ivoa.xml.vospace.v2.Property;
@@ -36,6 +40,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.w3c.dom.Document;
import java.util.List;

@SpringBootTest
@AutoConfigureMockMvc
@@ -192,6 +197,51 @@ public class TransferControllerTest {
        verify(jobDao, times(1)).getJob(eq("123"));
    }
    
    @Test
    public void testGetJobs() throws Exception {
       
        when(jobDao.getJobs(eq("user1"), any(), any(), any(), any()))
                .thenReturn(this.getFakeJobs());
        
        mockMvc.perform(get("/transfers")
                .header("Authorization", "Bearer user1_token")
                .param("LAST", "-3")
                .accept(MediaType.APPLICATION_XML))                
                .andDo(print())
                .andExpect(status().is4xxClientError());
                                
        
        String xml2 = mockMvc.perform(get("/transfers")
                .header("Authorization", "Bearer user1_token")
                .accept(MediaType.APPLICATION_XML))                
                .andDo(print())
                .andExpect(status().isOk())
                .andReturn().getResponse().getContentAsString();
    }

    private Jobs getFakeJobs() {
        Jobs jobs = new Jobs();
        jobs.setVersion("1.1");
        List<ShortJobDescription> sjdList = jobs.getJobref();
        sjdList.add(getFakeSJD1());

        return jobs;
    }

    private ShortJobDescription getFakeSJD1() {
        ShortJobDescription sjd = new ShortJobDescription();
        sjd.setId("pippo1");
        sjd.setPhase(ExecutionPhase.QUEUED);
        sjd.setOwnerId("user1");
        sjd.setType(JobService.JobType.pullFromVoSpace.toString());

        LocalDateTime now = LocalDateTime.now();
        Timestamp ts = Timestamp.valueOf(now);
        sjd.setCreationTime(JobDAO.toXMLGregorianCalendar(ts));

        return sjd;
    }

    private JobSummary getFakePendingJob() {
        JobSummary job = new JobSummary();
        job.setPhase(ExecutionPhase.PENDING);
+122 −1
Original line number Diff line number Diff line
package it.inaf.oats.vospace.persistence;

import it.inaf.oats.vospace.JobService;
import java.util.List;
import javax.sql.DataSource;
import net.ivoa.xml.uws.v1.ExecutionPhase;
import net.ivoa.xml.uws.v1.JobSummary;
import net.ivoa.xml.vospace.v2.ContainerNode;
import net.ivoa.xml.uws.v1.ShortJobDescription;
import net.ivoa.xml.vospace.v2.Transfer;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -14,6 +16,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.util.Optional;
import java.time.LocalDateTime;
import java.time.Month;
import net.ivoa.xml.uws.v1.Jobs;

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {DataSourceConfig.class})
@@ -54,4 +60,119 @@ public class JobDAOTest {

        assertEquals(ExecutionPhase.EXECUTING, dao.getJob("123").get().getPhase());
    }

    @Test
    public void testJobsList() {
        // Check no arguments
        String user = "user1";
        List<ExecutionPhase> phaseList = List.of();
        List<JobService.JobType> directionList = List.of();
        Optional<LocalDateTime> after = Optional.ofNullable(null);
        Optional<Integer> last = Optional.ofNullable(null);

        Jobs jobs = dao.getJobs(user, phaseList, directionList, after, last);

        assertTrue(jobs != null);
        List<ShortJobDescription> sjdList = jobs.getJobref();
        assertTrue(sjdList != null);
        assertTrue(!sjdList.isEmpty());
        assertTrue(
                sjdList.stream().noneMatch(
                        (i) -> {
                            return i.getPhase().equals(ExecutionPhase.ARCHIVED);
                        }
                )
        );
        assertEquals(3, sjdList.size());
    }

    @Test
    public void testJobsListLimit() {
        // Check no arguments
        String user = "user1";
        List<ExecutionPhase> phaseList = List.of();
        List<JobService.JobType> directionList = List.of();
        Optional<LocalDateTime> after = Optional.ofNullable(null);
        Optional<Integer> last = Optional.of(2);

        Jobs jobs = dao.getJobs(user, phaseList, directionList, after, last);
        List<ShortJobDescription> sjdList = jobs.getJobref();
        assertEquals(2, sjdList.size());

    }

    @Test
    public void testJobsPhase() {
        // Check no arguments
        String user = "user1";
        List<ExecutionPhase> phaseList
                = List.of(ExecutionPhase.PENDING, ExecutionPhase.EXECUTING);
        List<JobService.JobType> directionList = List.of();
        Optional<LocalDateTime> after = Optional.ofNullable(null);
        Optional<Integer> last = Optional.ofNullable(null);

        Jobs jobs = dao.getJobs(user, phaseList, directionList, after, last);
        List<ShortJobDescription> sjdList = jobs.getJobref();
        assertEquals(sjdList.size(), 2);
        assertEquals("pippo5", sjdList.get(0).getId());
        assertEquals("pippo2", sjdList.get(1).getId());
    }

    @Test
    public void testJobsDirection() {
        // Check no arguments
        String user = "user1";
        List<ExecutionPhase> phaseList = List.of();
        List<JobService.JobType> directionList
                = List.of(JobService.JobType.pullFromVoSpace,
                        JobService.JobType.pullToVoSpace);

        Optional<LocalDateTime> after = Optional.ofNullable(null);
        Optional<Integer> last = Optional.ofNullable(null);
        Jobs jobs = dao.getJobs(user, phaseList, directionList, after, last);
        List<ShortJobDescription> sjdList = jobs.getJobref();
        assertEquals(2, sjdList.size());
        assertEquals("pippo3", sjdList.get(0).getId());
        assertEquals("pippo2", sjdList.get(1).getId());
    }

    @Test
    public void testJobsAfter() {
        // Check no arguments
        String user = "user1";
        List<ExecutionPhase> phaseList = List.of();
        List<JobService.JobType> directionList = List.of();

        LocalDateTime ldt
                = LocalDateTime.of(2013, Month.FEBRUARY, 7, 18, 15);
        Optional<LocalDateTime> after = Optional.of(ldt);

        Optional<Integer> last = Optional.ofNullable(null);
        Jobs jobs = dao.getJobs(user, phaseList, directionList, after, last);
        List<ShortJobDescription> sjdList = jobs.getJobref();
        assertEquals(2, sjdList.size());
        assertEquals("pippo5", sjdList.get(0).getId());
        assertEquals("pippo3", sjdList.get(1).getId());
    }

    @Test
    public void testJobsAllchecks() {
        // Check no arguments
        String user = "user1";
        List<ExecutionPhase> phaseList = List.of(ExecutionPhase.QUEUED, 
                ExecutionPhase.PENDING);
        List<JobService.JobType> directionList =
                List.of(JobService.JobType.pullFromVoSpace,
                        JobService.JobType.pullToVoSpace);

        LocalDateTime ldt
                = LocalDateTime.of(2013, Month.FEBRUARY, 7, 18, 15);
        Optional<LocalDateTime> after = Optional.of(ldt);

        Optional<Integer> last = Optional.of(2);
        Jobs jobs = dao.getJobs(user, phaseList, directionList, after, last);
        List<ShortJobDescription> sjdList = jobs.getJobref();
        assertEquals(1, sjdList.size());
        assertEquals("pippo3", sjdList.get(0).getId());
    }
}
Loading