001/**
002 * Copyright 2014 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;
017
018
019import java.util.HashMap;
020import java.util.Map;
021
022import javax.xml.bind.annotation.XmlAccessType;
023import javax.xml.bind.annotation.XmlAccessorType;
024import javax.xml.bind.annotation.XmlElement;
025import javax.xml.bind.annotation.XmlRootElement;
026
027import org.apache.commons.lang3.StringUtils;
028
029import core.tut.pori.context.ServiceInitializer;
030import service.tut.pori.contentanalysis.AsyncTask.TaskType;
031
032/**
033 * An implementation of AbstractTaskDetails, which can be used to define a photo analysis task, or a feedback task.
034 * 
035 * <h2>Conditional Elements</h2>
036 * <ul>
037 *  <li>{@value service.tut.pori.contentanalysis.Definitions#ELEMENT_DELETED_PHOTOLIST}</li>
038 *  <li>{@value service.tut.pori.contentanalysis.Definitions#ELEMENT_DISSIMILAR_PHOTOLIST}</li>
039 *  <li>{@value service.tut.pori.contentanalysis.Definitions#ELEMENT_PHOTOLIST}</li>
040 *  <li>{@value service.tut.pori.contentanalysis.Definitions#ELEMENT_REFERENCE_PHOTOLIST}</li>
041 *  <li>{@value service.tut.pori.contentanalysis.Definitions#ELEMENT_SIMILAR_PHOTOLIST}</li>
042 * </ul>
043 * 
044 * 
045 * One of {@value service.tut.pori.contentanalysis.Definitions#ELEMENT_PHOTOLIST}, {@value service.tut.pori.contentanalysis.Definitions#ELEMENT_REFERENCE_PHOTOLIST} or {@value service.tut.pori.contentanalysis.Definitions#ELEMENT_DELETED_PHOTOLIST} must be present in a task. If {@value service.tut.pori.contentanalysis.Definitions#ELEMENT_DISSIMILAR_PHOTOLIST} or {@value service.tut.pori.contentanalysis.Definitions#ELEMENT_SIMILAR_PHOTOLIST} is present, {@value service.tut.pori.contentanalysis.Definitions#ELEMENT_REFERENCE_PHOTOLIST} must be present.
046 * 
047 * When including {@link service.tut.pori.contentanalysis.SimilarPhotoList} and/or {@link service.tut.pori.contentanalysis.DissimilarPhotoList}, it is recommended to provide only a single reference photo in the {@link service.tut.pori.contentanalysis.ReferencePhotoList}, and the photos should not contain media objects with updated metadata (i.e. media object feedback). 
048 * For the media object feedback, a separate feedback task should be generated. 
049 * For tasks of type {@link service.tut.pori.contentanalysis.AsyncTask.TaskType#ANALYSIS} and {@link service.tut.pori.contentanalysis.AsyncTask.TaskType#BACKEND_FEEDBACK}, the valid list is {@link service.tut.pori.contentanalysis.PhotoList}, and for tasks of type {@link service.tut.pori.contentanalysis.AsyncTask.TaskType#FEEDBACK} the valid lists are {@link service.tut.pori.contentanalysis.DeletedPhotoList}, {@link service.tut.pori.contentanalysis.DissimilarPhotoList}, {@link service.tut.pori.contentanalysis.ReferencePhotoList} and {@link service.tut.pori.contentanalysis.SimilarPhotoList}.
050 * 
051 * <h2>Optional Elements</h2>
052 * <ul>
053 *  <li>{@value service.tut.pori.contentanalysis.Definitions#ELEMENT_BACKEND_STATUS_LIST}</li>
054 *  <li>{@value service.tut.pori.contentanalysis.Definitions#ELEMENT_USER_CONFIDENCE}, recommended values are 0...1 normalized, though other values are also accepted.</li>
055 * </ul>
056 * 
057 * <h3>XML Example - Analysis Task</h3>
058 * 
059 * {@doc.restlet service="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_EXAMPLE]" method="[service.tut.pori.contentanalysis.Definitions#ELEMENT_TASK_DETAILS]" type="GET" query="[service.tut.pori.contentanalysis.reference.Definitions#PARAMETER_TASK_TYPE]=[service.tut.pori.contentanalysis.AsyncTask$TaskType#ANALYSIS]" body_uri=""}
060 * 
061 * <h3>XML Example - Backend Feedback Task</h3>
062 * 
063 * {@doc.restlet service="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_EXAMPLE]" method="[service.tut.pori.contentanalysis.Definitions#ELEMENT_TASK_DETAILS]" type="GET" query="[service.tut.pori.contentanalysis.reference.Definitions#PARAMETER_TASK_TYPE]=[service.tut.pori.contentanalysis.AsyncTask$TaskType#BACKEND_FEEDBACK]" body_uri=""}
064 * 
065 * <h3>XML Example - Feedback Task</h3>
066 * 
067 * {@doc.restlet service="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_EXAMPLE]" method="[service.tut.pori.contentanalysis.Definitions#ELEMENT_TASK_DETAILS]" type="GET" query="[service.tut.pori.contentanalysis.reference.Definitions#PARAMETER_TASK_TYPE]=[service.tut.pori.contentanalysis.AsyncTask$TaskType#FEEDBACK]" body_uri=""}
068 *   
069 * @see service.tut.pori.contentanalysis.DeletedPhotoList
070 * @see service.tut.pori.contentanalysis.DissimilarPhotoList
071 * @see service.tut.pori.contentanalysis.SimilarPhotoList
072 * @see service.tut.pori.contentanalysis.PhotoList
073 * @see service.tut.pori.contentanalysis.ReferencePhotoList
074 */
075@XmlRootElement(name=Definitions.ELEMENT_TASK_DETAILS)
076@XmlAccessorType(XmlAccessType.NONE)
077public final class PhotoTaskDetails extends AbstractTaskDetails{
078  private PhotoParameters _analysisParameters = null;
079  @XmlElement(name = Definitions.ELEMENT_DELETED_PHOTOLIST)
080  private DeletedPhotoList _deletedPhotoList = null;
081  @XmlElement(name = Definitions.ELEMENT_DISSIMILAR_PHOTOLIST)
082  private DissimilarPhotoList _dissimilarPhotoList = null;
083  @XmlElement(name = Definitions.ELEMENT_PHOTOLIST)
084  private PhotoList _photoList = null;
085  @XmlElement(name = Definitions.ELEMENT_SIMILAR_PHOTOLIST)
086  private SimilarPhotoList _similarPhotoList = null; 
087  @XmlElement(name = Definitions.ELEMENT_REFERENCE_PHOTOLIST)
088  private ReferencePhotoList _referencePhotoList = null;
089  @XmlElement(name = Definitions.ELEMENT_USER_CONFIDENCE)
090  private Double _userConfidence = null;
091
092  /**
093   * 
094   * @return photo list
095   */
096  public PhotoList getPhotoList() {
097    return _photoList;
098  }
099
100  /**
101   * 
102   */
103  public PhotoTaskDetails(){
104    super();
105  }
106  
107  /**
108   * 
109   * @param type
110   */
111  public PhotoTaskDetails(TaskType type){
112    super();
113    setTaskType(type);
114  }
115
116  /**
117   * 
118   * @param photoList
119   * @see #getPhotoList()
120   */
121  public void setPhotoList(PhotoList photoList) {
122    _photoList = photoList;
123  }
124
125  /**
126   * 
127   * @return list of deleted photos
128   * @see #setDeletedPhotoList(DeletedPhotoList)
129   */
130  public DeletedPhotoList getDeletedPhotoList() {
131    return _deletedPhotoList;
132  }
133
134  /**
135   * 
136   * @param deletedPhotoList
137   * @see #getDeletedPhotoList()
138   */
139  public void setDeletedPhotoList(DeletedPhotoList deletedPhotoList) {
140    _deletedPhotoList = deletedPhotoList;
141  }
142
143  /**
144   * @see #getReferencePhotoList()
145   * @see #setSimilarPhotoList(SimilarPhotoList)
146   * 
147   * @return list of photos similar to reference photos
148   */
149  public SimilarPhotoList getSimilarPhotoList() {
150    return _similarPhotoList;
151  }
152
153  /**
154   * 
155   * @param similarPhotoList
156   * @see #getSimilarPhotoList()
157   */
158  public void setSimilarPhotoList(SimilarPhotoList similarPhotoList) {
159    _similarPhotoList = similarPhotoList;
160  }
161
162  /**
163   * @see #getReferencePhotoList()
164   * @see #setDissimilarPhotoList(DissimilarPhotoList)
165   * 
166   * @return list of photos dissimilar to the reference photos
167   */
168  public DissimilarPhotoList getDissimilarPhotoList() {
169    return _dissimilarPhotoList;
170  }
171
172  /**
173   * 
174   * @param dissimilarPhotoList
175   * @see #getDissimilarPhotoList()
176   */
177  public void setDissimilarPhotoList(DissimilarPhotoList dissimilarPhotoList) {
178    _dissimilarPhotoList = dissimilarPhotoList;
179  }
180  
181  /**
182   * @see #getDissimilarPhotoList()
183   * @see #getSimilarPhotoList()
184   * @see #setReferencePhotoList(ReferencePhotoList)
185   * 
186   * @return reference photos for similar and/or dissimilar photos
187   */
188  public ReferencePhotoList getReferencePhotoList() {
189    return _referencePhotoList;
190  }
191
192  /**
193   * @param referencePhotoList the referencePhotoList to set
194   * @see #getReferencePhotoList()
195   */
196  public void setReferencePhotoList(ReferencePhotoList referencePhotoList) {
197    _referencePhotoList = referencePhotoList;
198  }
199  
200  /**
201   * 
202   * @param photo
203   * @see #getReferencePhotoList()
204   */
205  public void addReferencePhoto(Photo photo){
206    if(_referencePhotoList == null){
207      _referencePhotoList = new ReferencePhotoList();
208    }
209    _referencePhotoList.addPhoto(photo);
210  }
211  
212  /**
213   * 
214   * @param photo
215   * @see #getPhotoList()
216   */
217  public void addPhoto(Photo photo){
218    if(_photoList == null){
219      _photoList = new PhotoList();
220    }
221    _photoList.addPhoto(photo);
222  }
223  
224  /**
225   * 
226   * @param photo
227   * @see #getDeletedPhotoList()
228   */
229  public void addDeletedPhoto(Photo photo){
230    if(_deletedPhotoList == null){
231      _deletedPhotoList = new DeletedPhotoList();
232    }
233    _deletedPhotoList.addPhoto(photo);
234  }
235  
236  /**
237   * 
238   * @param photo
239   * @see #getSimilarPhotoList()
240   */
241  public void addSimilarPhoto(Photo photo){
242    if(_similarPhotoList == null){
243      _similarPhotoList = new SimilarPhotoList();
244    }
245    _similarPhotoList.addPhoto(photo);
246  }
247  
248  /**
249   * 
250   * @param photo
251   * @see #getDissimilarPhotoList()
252   */
253  public void addDissimilarPhoto(Photo photo){
254    if(_dissimilarPhotoList == null){
255      _dissimilarPhotoList = new DissimilarPhotoList();
256    }
257    _dissimilarPhotoList.addPhoto(photo);
258  }
259  
260  /**
261   * 
262   * @return true if no photo lists are given or the lists are empty
263   */
264  public boolean isEmpty(){
265    if(!PhotoList.isEmpty(_photoList) || !ReferencePhotoList.isEmpty(_referencePhotoList) || !DeletedPhotoList.isEmpty(_deletedPhotoList) || !SimilarPhotoList.isEmpty(_similarPhotoList) || !DissimilarPhotoList.isEmpty(_dissimilarPhotoList)){
266      return false;
267    }else{
268      return true;
269    }
270  }
271  
272  /**
273   * 
274   * @return confidence of the task owner, or null if unknown
275   * @see #setUserConfidence(Double)
276   */
277  public Double getUserConfidence() {
278    return _userConfidence;
279  }
280
281  /**
282   * 
283   * @param userConfidence
284   * @see #getUserConfidence()
285   */
286  public void setUserConfidence(Double userConfidence) {
287    _userConfidence = userConfidence;
288  }
289
290  @Override
291  public Map<String, String> getMetadata() {
292    if(_userConfidence == null){
293      return super.getMetadata();
294    }else{
295      Map<String, String> metadata = super.getMetadata();
296      if(metadata == null){
297        metadata = new HashMap<>(1);
298        super.setMetadata(metadata);
299      }
300      metadata.put(Definitions.ELEMENT_CONFIDENCE, _userConfidence.toString());
301      return metadata;
302    }
303  }
304
305  @Override
306  public void setMetadata(Map<String, String> metadata) {
307    if(metadata == null){
308      _userConfidence = null;
309    }else{
310      String confidence = metadata.get(Definitions.ELEMENT_CONFIDENCE);
311      if(StringUtils.isBlank(confidence)){
312        _userConfidence = null;
313      }else{
314        _userConfidence = Double.valueOf(confidence);
315      }
316    }
317    super.setMetadata(metadata);
318  }
319  
320  @Override
321  public String getCallbackUri() {
322    String callbackUri = super.getCallbackUri();
323    return (StringUtils.isBlank(callbackUri) ? generateFinishedCallbackUri() : callbackUri);
324  }
325
326  /**
327   * 
328   * @return the default task finished callback uri
329   */
330  public static String generateFinishedCallbackUri(){
331    return ServiceInitializer.getPropertyHandler().getRESTBindContext()+Definitions.SERVICE_CA+"/"+Definitions.METHOD_TASK_FINISHED;
332  }
333
334  @Override
335  public PhotoParameters getTaskParameters() {
336    return _analysisParameters;
337  }
338
339  @Override
340  public void setTaskParameters(TaskParameters parameters) {
341    if(parameters == null){
342      _analysisParameters = null;
343    }else if(parameters instanceof PhotoParameters){
344      setTaskParameters((PhotoParameters) parameters);
345    }else{
346      _analysisParameters = new PhotoParameters();
347    }
348  }
349  
350  /**
351   * 
352   * @param parameters
353   */
354  public void setTaskParameters(PhotoParameters parameters) {
355    _analysisParameters = parameters;
356  }
357}