package com.griddynamics.jagger.dbapi.util;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.griddynamics.jagger.dbapi.dto.TestInfoDto;
import com.griddynamics.jagger.dbapi.entity.TaskData;
import com.griddynamics.jagger.util.Decision;
import org.springframework.stereotype.Component;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Created by kgribov on 3/17/14.
*/
@Component
public class FetchUtil {
private EntityManager entityManager;
@PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
/**
* @return multi map <test-group id, tests ids>
*/
public Multimap<Long, Long> getTestGroupIdsByTestIds(Set<Long> taskIds) {
Multimap<Long, Long> resultMap = HashMultimap.create();
List<String> sessionIds = getSessionIdsByTaskIds(taskIds);
if (sessionIds.isEmpty()) {
// return empty Map, as we did not find any data we wanted
return resultMap;
}
List<Object[]> groupToTaskList = getGroupToTaskIdsList(sessionIds, taskIds);
for (Object[] objects : groupToTaskList) {
Long groupId = ((Number) objects[0]).longValue();
Long taskId = ((Number) objects[1]).longValue();
resultMap.put(groupId, taskId);
}
return resultMap;
}
/**
* @param sessionIds session ids of sessions to select pairs
* @param taskIds TaskData ids of tests to select pairs
* @return pairs as (test group id, test id)
*/
private List<Object[]> getGroupToTaskIdsList(Collection<String> sessionIds, Collection<Long> taskIds) {
return entityManager.createNativeQuery("SELECT grTaskData.id, mysome.taskDataId FROM" +
" (" +
" SELECT * FROM TaskData AS td WHERE td.sessionId IN (:sessionIds) " +
" ) AS grTaskData JOIN" +
" (" +
" SELECT td2.sessionId, td2.id AS taskDataId, wd.parentId FROM" +
" ( " +
" SELECT wd.parentId, wd.sessionId, wd.taskId FROM WorkloadData AS wd WHERE wd.sessionId IN (:sessionIds)" +
" ) AS wd JOIN " +
" TaskData AS td2" +
" ON td2.id IN (:taskIds)" +
" AND wd.sessionId = td2.sessionId" +
" AND wd.taskId=td2.taskId" +
" ) AS mysome " +
" ON grTaskData.sessionId = mysome.sessionId AND grTaskData.taskId=mysome.parentId")
.setParameter("sessionIds", sessionIds)
.setParameter("taskIds", taskIds)
.getResultList();
}
/**
* @param taskIds TaskData ids for required sessions
* @return list of session Ids
*/
public List<String> getSessionIdsByTaskIds(Set<Long> taskIds) {
return entityManager.createNativeQuery("SELECT DISTINCT taskData.sessionId FROM TaskData taskData " +
"WHERE taskData.id IN (:ids)")
.setParameter("ids", taskIds)
.getResultList();
}
/**
* Returns test info for specified tests ids
*
* @param taskIds - selected test ids
* @return map <testId, map <sessionId, test info>> of test info
*/
public Map<Long, Map<String, TestInfoDto>> getTestInfoByTaskIds(Set<Long> taskIds) throws RuntimeException {
if (taskIds.isEmpty()) {
return Collections.emptyMap();
}
@SuppressWarnings("all")
List<Object[]> objectsList = (List<Object[]>) entityManager.createNativeQuery(
"SELECT wtd.sessionId, wtd.clock, wtd.clockValue, wtd.termination, finalTaskData.id," +
"finalTaskData.startTime, finalTaskData.endTime, wtd.number, finalTaskData.status " +
"FROM WorkloadTaskData AS wtd JOIN " +
"(SELECT wd.startTime, wd.endTime, wd.taskId, wd.sessionId, taskData.id, taskData.status FROM WorkloadData " +
"AS wd JOIN " +
"( SELECT td.id, td.sessionId, td.taskId, td.status FROM TaskData td WHERE td.id IN (:taskDataIds) " +
") AS taskData " +
"ON wd.taskId=taskData.taskId AND wd.sessionId=taskData.sessionId" +
") AS finalTaskData " +
"ON wtd.sessionId=finalTaskData.sessionId AND wtd.taskId=finalTaskData.taskId ORDER BY finalTaskData.startTime")
.setParameter("taskDataIds", taskIds)
.getResultList();
Map<Long, Map<String, TestInfoDto>> resultMap = Maps.newLinkedHashMap();
for (Object[] objects : objectsList) {
Long taskId = ((BigInteger) objects[4]).longValue();
String clock = (String) objects[1];
Integer clockValue = (Integer) objects[2];
String termination = (String) objects[3];
String sessionId = (String) objects[0];
Date startTime = (Date) objects[5];
Date endTime = (Date) objects[6];
Integer number = (Integer) objects[7];
if (number == null) {
number = 0;
}
TaskData.ExecutionStatus executionStatus = TaskData.ExecutionStatus.valueOf((String) objects[8]);
Decision status = Decision.OK;
if (TaskData.ExecutionStatus.FAILED.equals(executionStatus)) {
status = Decision.FATAL;
}
if (!resultMap.containsKey(taskId)) {
resultMap.put(taskId, new HashMap<>());
}
TestInfoDto testInfo = new TestInfoDto();
testInfo.setClock(clock);
testInfo.setClockValue(clockValue);
testInfo.setTermination(termination);
testInfo.setStartTime(startTime);
testInfo.setEndTime(endTime);
testInfo.setNumber(number);
testInfo.setStatus(status);
resultMap.get(taskId).put(sessionId, testInfo);
}
return resultMap;
}
/**
* Returns task data, corresponding to defined pair of taskIs and sessionId
*
* @param taskId - TaskData taskId
* @param sessionId - session id
* @return TaskData for selected params
*/
public TaskData getTaskData(String taskId, String sessionId) {
return (TaskData) entityManager.createQuery("select t from TaskData t where sessionId=(:sessionId) and taskId=(:taskId)")
.setParameter("sessionId", sessionId)
.setParameter("taskId", taskId)
.getSingleResult();
}
/**
* Returns task data, corresponding to TaskData ids
*
* @param ids - TaskData ids
* @return map <TaskData id, TaskData>
*/
public Map<Long, TaskData> getTaskData(Collection<Long> ids) {
List<TaskData> taskDataList = (List<TaskData>) entityManager.createQuery("select t from TaskData t where id in (:ids)")
.setParameter("ids", ids)
.getResultList();
Map<Long, TaskData> result = new HashMap<>();
for (TaskData taskData : taskDataList) {
result.put(taskData.getId(), taskData);
}
return result;
}
}