001/** 002 * Copyright 2015 Tampere University of Technology, Pori Department 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package service.tut.pori.contentanalysis.video; 017 018import java.util.EnumSet; 019import java.util.List; 020 021import org.apache.commons.lang3.tuple.Pair; 022import org.apache.log4j.Logger; 023import org.springframework.beans.factory.annotation.Autowired; 024 025import service.tut.pori.contentanalysis.AbstractTaskDetails; 026import service.tut.pori.contentanalysis.AnalysisBackend; 027import service.tut.pori.contentanalysis.AsyncTask.TaskType; 028import service.tut.pori.contentanalysis.MediaTaskDAO; 029import core.tut.pori.http.parameters.DataGroups; 030import core.tut.pori.http.parameters.Limits; 031import core.tut.pori.users.UserIdentity; 032import core.tut.pori.utils.MediaUrlValidator.MediaType; 033 034/** 035 * Class for storing video tasks 036 */ 037public class VideoTaskDAO extends MediaTaskDAO { 038 private static final DataGroups BASIC = new DataGroups(DataGroups.DATA_GROUP_BASIC); 039 private static final Logger LOGGER = Logger.getLogger(VideoTaskDAO.class); 040 private static final EnumSet<MediaType> MEDIA_TYPES = EnumSet.of(MediaType.VIDEO); 041 @Autowired 042 private VideoDAO _videoDAO = null; 043 044 @Override 045 public VideoTaskDetails getTask(Integer backendId, DataGroups dataGroups, Limits limits, Long taskId) throws IllegalArgumentException { 046 Pair<TaskType, UserIdentity> type = getTaskType(backendId, taskId); 047 if(type == null){ 048 LOGGER.warn("Failed to resolve task type."); 049 return null; 050 } 051 052 if(backendId == null){ 053 LOGGER.debug("No backend id given, will not check data groups."); 054 }else if(DataGroups.isEmpty(dataGroups)){ 055 LOGGER.debug("No datagroups given, retrieving default data groups."); 056 AnalysisBackend backend = getBackendDAO().getBackend(backendId); 057 if(backend == null){ 058 throw new IllegalArgumentException("Backend, id: "+backendId+" does not exist."); 059 } 060 dataGroups = backend.getDefaultTaskDataGroups(); 061 } 062 063 VideoTaskDetails details = new VideoTaskDetails(type.getLeft()); 064 details.setBackendId(backendId); 065 details.setTaskId(taskId); 066 details.setUserId(type.getRight()); 067 getVideos(dataGroups, details, limits); 068 069 getTaskMetadata(details); 070 071 if(DataGroups.hasDataGroup(service.tut.pori.contentanalysis.Definitions.DATA_GROUP_BACKEND_STATUS, dataGroups)){ 072 getBackendStatusList(details); 073 } 074 075 if(details.isEmpty()){ 076 LOGGER.warn("Task, id: "+taskId+" has no content."); 077 return null; 078 }else{ 079 return details; 080 } 081 } 082 083 /** 084 * retrieve and set the videos for the task 085 * 086 * @param dataGroups 087 * @param details 088 * @param limits 089 */ 090 private void getVideos(DataGroups dataGroups, VideoTaskDetails details, Limits limits){ 091 Long taskId = details.getTaskId(); 092 093 List<String> videoGUIDs = getTaskGUIDs(limits, taskId, GUIDType.MEDIA); 094 if(videoGUIDs != null){ 095 LOGGER.debug("Retrieving video list..."); 096 TaskType taskType = details.getTaskType(); 097 switch(taskType){ 098 case ANALYSIS: // if task type is analysis, retrieve video list based solely on the given datagroups 099 LOGGER.debug("Retrieving all videos for the task based on the given dataGroups, for task of type "+TaskType.ANALYSIS.name()+", id: "+taskId); 100 details.setVideoList(_videoDAO.getVideos(dataGroups, videoGUIDs, null, null, null)); 101 break; 102 case BACKEND_FEEDBACK: 103 case FEEDBACK: // ignore result_info datagroup for FEEDBACK, status will be checked later 104 LOGGER.debug("Retrieving all videos for the task based on datagroup "+DataGroups.DATA_GROUP_BASIC+", for task of type "+taskType.name()+", id: "+taskId); 105 VideoList videos = _videoDAO.getVideos(BASIC, videoGUIDs, null, null, null); // use basic to get all basic/core details of the video 106 if(!VideoList.isEmpty(videos)){ 107 details.setVideoList(videos); 108 setMediaObjects(dataGroups, limits, videos.getVideos(), MEDIA_TYPES, taskId); 109 } 110 break; 111 default: // should not happen 112 throw new UnsupportedOperationException("Unsupported "+TaskType.class.toString()); 113 } 114 }else if((videoGUIDs = getTaskGUIDs(limits, taskId, GUIDType.DELETED_MEDIA)) != null){ 115 LOGGER.debug("Retrieving deleted video list..."); 116 for(String guid : videoGUIDs){ 117 details.addDeletedVideo(new Video(guid)); 118 } 119 }else{ 120 LOGGER.warn("No content..."); 121 return; 122 } 123 124 if(DataGroups.hasDataGroup(service.tut.pori.contentanalysis.Definitions.DATA_GROUP_STATUS, dataGroups)){ 125 LOGGER.debug("Retrieving video status information for task, id: "+taskId); 126 getMediaStatus(details.getVideoList().getVideos()); 127 getMediaStatus(details.getDeletedVideoList().getVideos()); 128 } 129 } 130 131 /** 132 * 133 * @param details 134 * @return id of the generated task 135 * @throws UnsupportedOperationException 136 * @throws IllegalArgumentException 137 */ 138 public Long insertTask(VideoTaskDetails details) throws UnsupportedOperationException, IllegalArgumentException { 139 TaskType type = details.getTaskType(); 140 switch(type){ 141 case ANALYSIS: 142 case FEEDBACK: 143 case BACKEND_FEEDBACK: 144 break; 145 default: 146 throw new UnsupportedOperationException("TaskType not supported: "+type.name()); 147 } 148 149 Long taskId = insertTask((AbstractTaskDetails) details); 150 if(taskId == null){ 151 throw new IllegalArgumentException("Failed to add new task."); 152 } 153 154 insertTaskGUIDs(details); 155 insertTaskMediaObjects(details); 156 157 return taskId; 158 } 159 160 /** 161 * This will also set video statuses, if any are present. Note that even through status elements can appear in any video list, 162 * creating two different lists with identical GUIDs, and conflicting status lists may create undefined behavior. 163 * 164 * @param details 165 */ 166 private void insertTaskGUIDs(VideoTaskDetails details){ 167 Long taskId = details.getTaskId(); 168 VideoList videos = details.getVideoList(); 169 if(VideoList.isEmpty(videos)){ 170 LOGGER.debug("No videos for task, id: "+taskId); 171 }else{ 172 insertTaskGUIDs(videos.getVideos(), taskId, GUIDType.MEDIA); 173 } 174 175 DeletedVideoList delVideos = details.getDeletedVideoList(); 176 if(DeletedVideoList.isEmpty(delVideos)){ 177 LOGGER.debug("No deleted videos for task, id: "+taskId); 178 }else{ 179 insertTaskGUIDs(delVideos.getVideos(), taskId, GUIDType.DELETED_MEDIA); 180 } 181 } 182 183 /** 184 * Note that media objects provided for any other list than the basic VideoList will be ignored. 185 * 186 * @param details 187 * @see service.tut.pori.contentanalysis.video.VideoTaskDetails#getVideoList() 188 */ 189 private void insertTaskMediaObjects(VideoTaskDetails details){ 190 VideoList videos = details.getVideoList(); 191 Long taskId = details.getTaskId(); 192 if(VideoList.isEmpty(videos)){ 193 LOGGER.debug("No videos for task, id: "+taskId); 194 }else{ 195 for(Video v : videos.getVideos()){ 196 insertTaskMediaObjects(v.getGUID(), taskId, v.getMediaObjects()); 197 } // for videos 198 } 199 } 200}