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}