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.reference;
017
018import java.io.IOException;
019import java.io.InputStream;
020
021import org.apache.commons.io.IOUtils;
022import org.apache.log4j.Logger;
023
024import service.tut.pori.contentanalysis.PhotoParameters.AnalysisType;
025import service.tut.pori.contentanalysis.CAContentCore.ServiceType;
026import service.tut.pori.contentanalysis.Definitions;
027import service.tut.pori.contentanalysis.PhotoFeedbackList;
028import service.tut.pori.contentanalysis.PhotoList;
029import service.tut.pori.contentanalysis.MediaObjectList;
030import core.tut.pori.http.RedirectResponse;
031import core.tut.pori.http.Response;
032import core.tut.pori.http.annotations.HTTPAuthenticationParameter;
033import core.tut.pori.http.annotations.HTTPMethodParameter;
034import core.tut.pori.http.annotations.HTTPService;
035import core.tut.pori.http.annotations.HTTPServiceMethod;
036import core.tut.pori.http.parameters.AuthenticationParameter;
037import core.tut.pori.http.parameters.DataGroups;
038import core.tut.pori.http.parameters.InputStreamParameter;
039import core.tut.pori.http.parameters.IntegerParameter;
040import core.tut.pori.http.parameters.Limits;
041import core.tut.pori.http.parameters.LongParameter;
042import core.tut.pori.http.parameters.StringParameter;
043import core.tut.pori.utils.XMLFormatter;
044
045/**
046 * Reference implementation for client API methods.
047 * 
048 * <h1>Implementation Service path {@value service.tut.pori.contentanalysis.Definitions#SERVICE_CA}</h1>
049 * 
050 * @see service.tut.pori.contentanalysis.ContentAnalysisService
051 *
052 */
053@HTTPService(name = service.tut.pori.contentanalysis.reference.Definitions.SERVICE_CA_REFERENCE_CLIENT)
054public class ClientService {
055  private static final Logger LOGGER = Logger.getLogger(ClientService.class);
056  private XMLFormatter _formatter = new XMLFormatter();
057  
058  /**
059   * Search for photos which contain the given keywords, or keywords closely related or associated with the keywords. Non-authenticated users only have access to publicly available content.
060   * 
061   * <h2>Example Query:</h2>
062   *
063   * GET /rest/{@value service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT}/{@value service.tut.pori.contentanalysis.Definitions#METHOD_SEARCH_SIMILAR_BY_KEYWORD}?{@value service.tut.pori.contentanalysis.Definitions#PARAMETER_KEYWORDS}=cute<br>
064   *
065   * <h2>Example Result:</h2>
066   * 
067   * {@doc.restlet service="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT]" method="[service.tut.pori.contentanalysis.Definitions#METHOD_SEARCH_SIMILAR_BY_KEYWORD]" type="GET" query="[service.tut.pori.contentanalysis.Definitions#PARAMETER_KEYWORDS]=cute" body_uri=""}
068   * 
069   * @param authenticatedUser
070   * @param keywords any number of keywords for the search. 
071   * @param dataGroups For supported data groups, see {@link #retrieveMediaObjects(AuthenticationParameter, DataGroups, Limits, IntegerParameter, StringParameter)}
072   * @param limits paging limits
073   * @param serviceIds If given, search is targeted only to the services with the listed ids. For supported service types, see {@link service.tut.pori.contentanalysis.CAContentCore.ServiceType}.
074   * @param userIdFilters If given, the search will return photos owned by the given user (provided that the currently logged in user has the required permissions).
075   * @return See {@link service.tut.pori.contentanalysis.PhotoList}
076   */
077  @HTTPServiceMethod(name = Definitions.METHOD_SEARCH_SIMILAR_BY_KEYWORD, acceptedMethods={core.tut.pori.http.Definitions.METHOD_GET})
078  public Response searchSimilarByKeyword(
079      @HTTPAuthenticationParameter(required = false) AuthenticationParameter authenticatedUser,
080      @HTTPMethodParameter(name = Definitions.PARAMETER_KEYWORDS) StringParameter keywords, 
081      @HTTPMethodParameter(name = DataGroups.PARAMETER_DEFAULT_NAME, required = false) DataGroups dataGroups,
082      @HTTPMethodParameter(name = Limits.PARAMETER_DEFAULT_NAME, required = false) Limits limits,
083      @HTTPMethodParameter(name = Definitions.PARAMETER_SERVICE_ID, required = false) IntegerParameter serviceIds,
084      @HTTPMethodParameter(name = service.tut.pori.users.Definitions.PARAMETER_USER_ID, required = false) LongParameter userIdFilters
085      ) 
086  {
087    return CAReferenceCore.searchByKeyword(authenticatedUser.getUserIdentity(), keywords.getValues(), dataGroups, limits, ServiceType.fromIdArray(serviceIds.getValues()), userIdFilters.getValues());
088  }
089  
090  /**
091   * Search for photos which are similar to the photo designated by the given GUID parameter. Non-authenticated users only have access to publicly available content.
092   * 
093   * <h2>Example Query:</h2>
094   *
095   * GET /rest/{@value service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT}/{@value service.tut.pori.contentanalysis.Definitions#METHOD_SEARCH_SIMILAR_BY_ID}?{@value service.tut.pori.contentanalysis.Definitions#PARAMETER_GUID}=1<br>
096   *
097   * <h2>Example Result:</h2>
098   * 
099   * {@doc.restlet service="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT]" method="[service.tut.pori.contentanalysis.Definitions#METHOD_SEARCH_SIMILAR_BY_ID]" type="GET" query="[service.tut.pori.contentanalysis.Definitions#PARAMETER_GUID]=1" body_uri=""}
100   * 
101   * @param authenticatedUser
102   * @param analysisType optional list of analysis types to use for the search operation {@link service.tut.pori.contentanalysis.PhotoParameters.AnalysisType}
103   * @param guid photo GUID
104   * @param dataGroups For supported data groups, see {@link #retrieveMediaObjects(AuthenticationParameter, DataGroups, Limits, IntegerParameter, StringParameter)}
105   * @param limits paging limits
106   * @param serviceIds If given, search is targeted only to the services with the listed ids. For supported service types, see {@link service.tut.pori.contentanalysis.CAContentCore.ServiceType}.
107   * @param userIdFilters If given, the search will return photos owned by the given user (provided that the currently logged in user has the required permissions).
108   * @return See {@link service.tut.pori.contentanalysis.PhotoList}
109   */
110  @HTTPServiceMethod(name = Definitions.METHOD_SEARCH_SIMILAR_BY_ID, acceptedMethods={core.tut.pori.http.Definitions.METHOD_GET})
111  public Response searchSimilarById(
112      @HTTPAuthenticationParameter(required = false) AuthenticationParameter authenticatedUser,
113      @HTTPMethodParameter(name = Definitions.PARAMETER_GUID) StringParameter guid, 
114      @HTTPMethodParameter(name = Definitions.PARAMETER_ANALYSIS_TYPE, required = false) StringParameter analysisType,
115      @HTTPMethodParameter(name = DataGroups.PARAMETER_DEFAULT_NAME, required = false) DataGroups dataGroups,
116      @HTTPMethodParameter(name = Limits.PARAMETER_DEFAULT_NAME, required = false) Limits limits,
117      @HTTPMethodParameter(name = Definitions.PARAMETER_SERVICE_ID, required = false) IntegerParameter serviceIds,
118      @HTTPMethodParameter(name = service.tut.pori.users.Definitions.PARAMETER_USER_ID, required = false) LongParameter userIdFilters
119      ) 
120  {
121    return CAReferenceCore.searchSimilarById(authenticatedUser.getUserIdentity(), AnalysisType.fromAnalysisTypeString(analysisType.getValues()), guid.getValue(), dataGroups, limits, ServiceType.fromIdArray(serviceIds.getValues()), userIdFilters.getValues());
122  }
123  
124  /**
125   * Search similar photos by giving a list of reference objects. All elements applicable to media objects are accepted as restrictive search terms. Note that missing elements (and element values) are assumed not to be included in the search, except "status" field, which is automatically assumed to be "USER_CONFIRMED" when no value is specified. The Media Object list is to be sent in the body of POST method. The Content-Type header MUST be set to "text/xml". The character set MUST be UTF-8. For example, "Content-Type: text/xml; charset=UTF-8".
126   * 
127   * <h2>Example Query:</h2>
128   * 
129   * POST /rest/{@value service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT}/{@value service.tut.pori.contentanalysis.Definitions#METHOD_SEARCH_SIMILAR_BY_OBJECT}<br>
130   * Content-Type: text/xml; charset=UTF-8<br><br>
131   *
132   * <b>[HTTP BODY STARTS]</b><br>
133   * 
134   * {@doc.restlet service="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_EXAMPLE]" method="[service.tut.pori.contentanalysis.Definitions#ELEMENT_MEDIA_OBJECTLIST]" type="GET" query="" body_uri=""} <br>
135   * 
136   * <b>[HTTP BODY ENDS]</b><br>
137   *
138   * <h2>Example Result:</h2>
139   * 
140   * {@doc.restlet service="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT]" method="[service.tut.pori.contentanalysis.Definitions#METHOD_SEARCH_SIMILAR_BY_OBJECT]" type="POST" query="" body_uri="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_EXAMPLE]/[service.tut.pori.contentanalysis.Definitions#ELEMENT_MEDIA_OBJECTLIST]"}
141   * 
142   * @param authenticatedUser
143   * @param dataGroups For supported data groups, see {@link #retrieveMediaObjects(AuthenticationParameter, DataGroups, Limits, IntegerParameter, StringParameter)}
144   * @param limits paging limits
145   * @param serviceIds If given, search is targeted only to the services with the listed ids. For supported service types, see {@link service.tut.pori.contentanalysis.CAContentCore.ServiceType}.
146   * @param userIdFilters If given, the search will return photos owned by the given user (provided that the currently logged in user has the required permissions).
147   * @param xml See {@link service.tut.pori.contentanalysis.MediaObjectList}
148   * @return See {@link service.tut.pori.contentanalysis.PhotoList}
149   */
150  @HTTPServiceMethod(name = Definitions.METHOD_SEARCH_SIMILAR_BY_OBJECT, acceptedMethods={core.tut.pori.http.Definitions.METHOD_POST})
151  public Response similarPhotosByObject(
152      @HTTPAuthenticationParameter(required = false) AuthenticationParameter authenticatedUser,
153      @HTTPMethodParameter(name = DataGroups.PARAMETER_DEFAULT_NAME, required = false) DataGroups dataGroups,
154      @HTTPMethodParameter(name = Limits.PARAMETER_DEFAULT_NAME, required = false) Limits limits,
155      @HTTPMethodParameter(name = Definitions.PARAMETER_SERVICE_ID, required = false) IntegerParameter serviceIds,
156      @HTTPMethodParameter(name = service.tut.pori.users.Definitions.PARAMETER_USER_ID, required = false) LongParameter userIdFilters,
157      @HTTPMethodParameter(name = InputStreamParameter.PARAMETER_DEFAULT_NAME, bodyParameter = true) InputStreamParameter xml
158      )
159  {
160    try {
161      String body = IOUtils.toString(xml.getValue()); // read the body
162      LOGGER.debug(body); // print to debug
163      try(InputStream input = IOUtils.toInputStream(body)){ // convert back to stream for unmarshal
164        return CAReferenceCore.similarPhotosByObject(authenticatedUser.getUserIdentity(), _formatter.toObject(input, MediaObjectList.class), dataGroups, limits, ServiceType.fromIdArray(serviceIds.getValues()), userIdFilters.getValues());
165      }
166    } catch (IOException ex) {
167      LOGGER.error(ex, ex);
168      return null;
169    }
170  }
171  
172  /**
173   * Search for photos which are similar to the photo designated by the given URL parameter. Non-authenticated users only have access to publicly available content.
174   * 
175   * <h2>Example Query:</h2>
176   *
177   * GET /rest/{@value service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT}/{@value service.tut.pori.contentanalysis.Definitions#METHOD_SEARCH_SIMILAR_BY_CONTENT}?{@value service.tut.pori.contentanalysis.Definitions#PARAMETER_URL}=http%3A%2F%2Fexample.org%2Fimage.jpg<br>
178   *
179   * <h2>Example Result:</h2>
180   * 
181   * {@doc.restlet service="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT]" method="[service.tut.pori.contentanalysis.Definitions#METHOD_SEARCH_SIMILAR_BY_CONTENT]" type="GET" query="[service.tut.pori.contentanalysis.Definitions#PARAMETER_URL]=http%3A%2F%2Fexample.org%2Fimage.jpg" body_uri=""}
182   * 
183   * @param authenticatedUser
184   * @param url publicly accessible URL with photo content
185   * @param analysisType optional list of analysis types to use for the search operation {@link service.tut.pori.contentanalysis.PhotoParameters.AnalysisType}
186   * @param dataGroups For supported data groups, see {@link #retrieveMediaObjects(AuthenticationParameter, DataGroups, Limits, IntegerParameter, StringParameter)}
187   * @param limits paging limits
188   * @param serviceIds If given, search is targeted only to the services with the listed ids. For supported service types, see {@link service.tut.pori.contentanalysis.CAContentCore.ServiceType}.
189   * @param userIdFilters If given, the search will return photos owned by the given user (provided that the currently logged in user has the required permissions).
190   * @return See {@link service.tut.pori.contentanalysis.PhotoList}
191   */
192  @HTTPServiceMethod(name = Definitions.METHOD_SEARCH_SIMILAR_BY_CONTENT, acceptedMethods={core.tut.pori.http.Definitions.METHOD_GET})
193  public Response searchSimilarByContent(
194      @HTTPAuthenticationParameter(required = false) AuthenticationParameter authenticatedUser,
195      @HTTPMethodParameter(name = Definitions.PARAMETER_URL) StringParameter url, 
196      @HTTPMethodParameter(name = Definitions.PARAMETER_ANALYSIS_TYPE, required = false) StringParameter analysisType, 
197      @HTTPMethodParameter(name = DataGroups.PARAMETER_DEFAULT_NAME, required = false) DataGroups dataGroups, 
198      @HTTPMethodParameter(name = Limits.PARAMETER_DEFAULT_NAME, required = false) Limits limits,
199      @HTTPMethodParameter(name = Definitions.PARAMETER_SERVICE_ID, required = false) IntegerParameter serviceIds, 
200      @HTTPMethodParameter(name = service.tut.pori.users.Definitions.PARAMETER_USER_ID, required = false) LongParameter userIdFilters
201      ) 
202  {  
203    return CAReferenceCore.searchByContent(authenticatedUser.getUserIdentity(), AnalysisType.fromAnalysisTypeString(analysisType.getValues()), url.getValue(), dataGroups, limits, ServiceType.fromIdArray(serviceIds.getValues()), userIdFilters.getValues());
204  }
205  
206  /**
207   * Redirects the client to the actual photo location (i.e. redirects calls targeted to static front-end URLs to dynamic service specific URLs).
208   * The redirection method takes GUID and service id as a parameter. The redirection URLs are automatically generated for analysis tasks and user's search results by the front-end.
209   * 
210   * <h2>Example Query:</h2>
211   *
212   * GET /rest/{@value service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT}/{@value service.tut.pori.contentanalysis.Definitions#METHOD_REDIRECT}?{@value service.tut.pori.contentanalysis.Definitions#PARAMETER_GUID}=1&amp;{@value service.tut.pori.contentanalysis.Definitions#PARAMETER_SERVICE_ID}=1
213   *
214   * <h2>Example Result:</h2>
215   * 
216   * REDIRECT / PHOTO CONTENT
217   * 
218   * @param authenticatedUser
219   * @param serviceId One of the supported service types, see {@link service.tut.pori.contentanalysis.CAContentCore.ServiceType}.
220   * @param guid photo GUID
221   * @return redirection
222   */
223  @HTTPServiceMethod(name = Definitions.METHOD_REDIRECT, acceptedMethods={core.tut.pori.http.Definitions.METHOD_GET})
224  public RedirectResponse r(
225      @HTTPAuthenticationParameter(required = false) AuthenticationParameter authenticatedUser,
226      @HTTPMethodParameter(name = Definitions.PARAMETER_SERVICE_ID) IntegerParameter serviceId,
227      @HTTPMethodParameter(name = Definitions.PARAMETER_GUID) StringParameter guid
228      )
229  {
230    return CAReferenceCore.generateTargetUrl(authenticatedUser.getUserIdentity(), ServiceType.fromServiceId(serviceId.getValue()), guid.getValue());
231  }
232  
233  /**
234   * The clients can use this method to update the details of photos. If media objects are updated, calling this method may trigger the generation of feedback task. 
235   * The request is to be sent in the body of POST method. The Content-Type header MUST be set to "text/xml". The character set MUST be UTF-8. For example, "Content-Type: text/xml; charset=UTF-8".
236   * 
237   * <h2>Example Query:</h2>
238   *
239   * POST /rest/{@value service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT}/{@value service.tut.pori.contentanalysis.Definitions#METHOD_UPDATE_PHOTO_METADATA}<br>
240   * Content-Type: text/xml; charset=UTF-8<br><br>
241   *
242   * <b>[HTTP BODY STARTS]</b><br>
243   * 
244   * {@doc.restlet service="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_EXAMPLE]" method="[service.tut.pori.contentanalysis.Definitions#ELEMENT_PHOTOLIST]" type="GET" query="" body_uri=""} <br>
245   * 
246   * <b>[HTTP BODY ENDS]</b><br>
247   *
248   * <h2>Example Result:</h2>
249   * 
250   * {@doc.restlet service="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT]" method="[service.tut.pori.contentanalysis.Definitions#METHOD_UPDATE_PHOTO_METADATA]" type="POST" query="" body_uri="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_EXAMPLE]/[service.tut.pori.contentanalysis.Definitions#ELEMENT_PHOTOLIST]"}
251   * 
252   * @param authenticatedUser Note: this method requires authentication, but for the reference implementation, anonymous access is granted.
253   * @param xml Only the result data should be in the body. See {@link service.tut.pori.contentanalysis.PhotoList}
254   */
255  @HTTPServiceMethod(name = Definitions.METHOD_UPDATE_PHOTO_METADATA, acceptedMethods={core.tut.pori.http.Definitions.METHOD_POST})
256  public void updatePhotos(
257      @HTTPAuthenticationParameter(required = false) AuthenticationParameter authenticatedUser, // in the real implementation this is required
258      @HTTPMethodParameter(name=InputStreamParameter.PARAMETER_DEFAULT_NAME, bodyParameter=true) InputStreamParameter xml
259      )
260  {
261    try {
262      String body = IOUtils.toString(xml.getValue()); // read the body
263      LOGGER.debug(body); // print to debug
264      try(InputStream input = IOUtils.toInputStream(body)){ // convert back to stream for unmarshal
265        CAReferenceCore.updatePhotos(authenticatedUser.getUserIdentity(), _formatter.toObject(input, PhotoList.class));
266      }
267    } catch (IOException ex) {
268      LOGGER.error(ex, ex);
269    }
270  }
271  
272  /**
273   * This method can be used to retrieve the metadata of one or multiple photos. Any combination of parameters may be given for retrieving only the desired content (filtering the results). If you only want a list of media objects, this can be done with Retrieve media Objects method. If the user is not authenticated, access is only permitted to publicly available content.
274   *
275   * <h2>Example Query:</h2>
276   *
277   * GET /rest/{@value service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT}/{@value service.tut.pori.contentanalysis.Definitions#METHOD_RETRIEVE_PHOTO_METADATA}<br>
278   *
279   * <h2>Example Result:</h2>
280   * 
281   * {@doc.restlet service="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT]" method="[service.tut.pori.contentanalysis.Definitions#METHOD_RETRIEVE_PHOTO_METADATA]" type="GET" query="" body_uri=""}
282   * 
283   * @param authenticatedUser
284   * @param guid One or more photo GUIDs for retrieval.
285   * @param dataGroups dataGroups For supported data groups, see {@link #retrieveMediaObjects(AuthenticationParameter, DataGroups, Limits, IntegerParameter, StringParameter)}
286   * @param limits paing limits
287   * @param serviceIds If given, only photos from the given services will be returned. For supported service types, see {@link service.tut.pori.contentanalysis.CAContentCore.ServiceType}.
288   * @param userIds If given, the search will return photos owned by the given user (provided that the currently logged in user has the required permissions).
289   * @return See {@link service.tut.pori.contentanalysis.PhotoList}
290   */
291  @HTTPServiceMethod(name = Definitions.METHOD_RETRIEVE_PHOTO_METADATA, acceptedMethods={core.tut.pori.http.Definitions.METHOD_GET})
292  public Response getPhotos(
293      @HTTPAuthenticationParameter(required = false) AuthenticationParameter authenticatedUser,
294      @HTTPMethodParameter(name = Definitions.PARAMETER_GUID, required=false) StringParameter guid,
295      @HTTPMethodParameter(name = DataGroups.PARAMETER_DEFAULT_NAME, required = false) DataGroups dataGroups,
296      @HTTPMethodParameter(name = Limits.PARAMETER_DEFAULT_NAME, required = false) Limits limits,
297      @HTTPMethodParameter(name = Definitions.PARAMETER_SERVICE_ID, required = false) IntegerParameter serviceIds,
298      @HTTPMethodParameter(name = service.tut.pori.users.Definitions.PARAMETER_USER_ID, required = false) LongParameter userIds
299      )
300  {
301    return CAReferenceCore.getPhotos(authenticatedUser.getUserIdentity(), guid.getValues(), dataGroups, limits, ServiceType.fromIdArray(serviceIds.getValues()), userIds.getValues());
302  }
303  
304  /**
305   * 
306   * The clients can use this method to deliver similarity feedback. An example case would be to notify the front-end that the results returned by a search query contain invalid results. Calling this method will trigger the generation of a feedback task.
307   * 
308   * The request must always contain a Photo List element, which contains at least one Photo for a reference, and a Similar Photo List and/or a Dissimilar Photo List element. The photo(s) in Dissimilar and Similar Photo Lists are thus similar or not similar with the passed reference photo, respectively.
309   * 
310   * The request is to be sent in the body of POST method. The Content-Type header MUST be set to "text/xml". The character set MUST be UTF-8. For example, "Content-Type: text/xml; charset=UTF-8".
311   * 
312   * <h2>Example Query:</h2>
313   *
314   * POST /rest/{@value service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT}/{@value service.tut.pori.contentanalysis.Definitions#METHOD_SIMILARITY_FEEDBACK}<br>
315   * Content-Type: text/xml; charset=UTF-8<br><br>
316   *
317   * <b>[HTTP BODY STARTS]</b><br>
318   * 
319   * {@doc.restlet service="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_EXAMPLE]" method="[service.tut.pori.contentanalysis.Definitions#ELEMENT_FEEDBACKLIST]" type="GET" query="" body_uri=""} <br>
320   * 
321   * <b>[HTTP BODY ENDS]</b><br>
322   *
323   * <h2>Example Result:</h2>
324   * 
325   * {@doc.restlet service="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT]" method="[service.tut.pori.contentanalysis.Definitions#METHOD_SIMILARITY_FEEDBACK]" type="POST" query="" body_uri="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_EXAMPLE]/[service.tut.pori.contentanalysis.Definitions#ELEMENT_FEEDBACKLIST]"}
326   * 
327   * @param authenticatedUser Note: this method requires authentication, but for the reference implementation, anonymous access is granted.
328   * @param xml Only the result data should be in the body. See {@link service.tut.pori.contentanalysis.PhotoFeedbackList}
329   */
330  @HTTPServiceMethod(name = Definitions.METHOD_SIMILARITY_FEEDBACK, acceptedMethods={core.tut.pori.http.Definitions.METHOD_POST})
331  public void similarityFeedback(
332      @HTTPAuthenticationParameter(required = false) AuthenticationParameter authenticatedUser,
333      @HTTPMethodParameter(name = InputStreamParameter.PARAMETER_DEFAULT_NAME, bodyParameter = true) InputStreamParameter xml
334      )
335  {
336    try {
337      String body = IOUtils.toString(xml.getValue()); // read the body
338      LOGGER.debug(body); // print to debug
339      try(InputStream input = IOUtils.toInputStream(body)){ // convert back to stream for unmarshal
340        CAReferenceCore.similarityFeedback(authenticatedUser.getUserIdentity(), _formatter.toObject(input, PhotoFeedbackList.class));
341      }
342    } catch (IOException ex) {
343      LOGGER.error(ex, ex);
344    }
345  }
346  
347  /**
348   * This method is for retrieving a list of media objects for the currently authenticated user by providing a set of request parameters (filters). If you want to retrieve media objects for a single photo, or for a list of photos, it can be done by using the Retrieve Photo Metadata method.
349   * 
350   * <h2>Example Query:</h2>
351   *
352   * GET /rest/{@value service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT}/{@value service.tut.pori.contentanalysis.Definitions#METHOD_RETRIEVE_MEDIA_OBJECTS}<br>
353   *
354   * <h2>Example Result:</h2>
355   * 
356   * {@doc.restlet service="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT]" method="[service.tut.pori.contentanalysis.Definitions#METHOD_RETRIEVE_MEDIA_OBJECTS]" type="GET" query="" body_uri=""}
357   * 
358   * @param authenticatedUser Note: this method requires authentication, but for the reference implementation, anonymous access is granted.
359   * @param dataGroups In addition to basic data groups the following groups are also supported: {@value service.tut.pori.contentanalysis.Definitions#DATA_GROUP_TIMECODES}, {@value service.tut.pori.contentanalysis.Definitions#DATA_GROUP_FACE}, {@value service.tut.pori.contentanalysis.Definitions#DATA_GROUP_KEYWORDS}, {@value service.tut.pori.contentanalysis.Definitions#DATA_GROUP_METADATA}, {@value service.tut.pori.contentanalysis.Definitions#DATA_GROUP_OBJECT}, {@value service.tut.pori.contentanalysis.Definitions#DATA_GROUP_BACKEND_REMOVED}, {@value service.tut.pori.contentanalysis.Definitions#DATA_GROUP_CANDIDATE}, {@value service.tut.pori.contentanalysis.Definitions#DATA_GROUP_USER_CONFIRMED} and {@value service.tut.pori.contentanalysis.Definitions#DATA_GROUP_USER_REJECTED}.
360   * @param limits paging limits
361   * @param serviceIds Return only objects retrieved from specific service(s). For supported service types, see {@link service.tut.pori.contentanalysis.CAContentCore.ServiceType}.
362   * @param mediaObjectIds Return only objects with the specified ids.
363   * @return See {@link service.tut.pori.contentanalysis.MediaObjectList}
364   */
365  @HTTPServiceMethod(name = Definitions.METHOD_RETRIEVE_MEDIA_OBJECTS, acceptedMethods={core.tut.pori.http.Definitions.METHOD_GET})
366  public Response retrieveMediaObjects(
367      @HTTPAuthenticationParameter(required = false) AuthenticationParameter authenticatedUser,
368      @HTTPMethodParameter(name = DataGroups.PARAMETER_DEFAULT_NAME, required = false) DataGroups dataGroups,
369      @HTTPMethodParameter(name = Limits.PARAMETER_DEFAULT_NAME, required = false) Limits limits,
370      @HTTPMethodParameter(name = Definitions.PARAMETER_SERVICE_ID, required = false) IntegerParameter serviceIds,
371      @HTTPMethodParameter(name = Definitions.PARAMETER_MEDIA_OBJECT_ID, required = false) StringParameter mediaObjectIds
372      )
373  {
374    return CAReferenceCore.getMediaObjects(authenticatedUser.getUserIdentity(), dataGroups, limits, ServiceType.fromIdArray(serviceIds.getValues()), mediaObjectIds.getValues());
375  }
376  
377  /**
378   * 
379   * This method is for removing photo metadata. Note that even though all metadata for the given photo(s) will be removed, the removal operation happens only in the scope of the system known ("front-end local") UID and no changes will be propagated to the content storage service hosting the original photo. This also means that synchronizing the external account will re-insert the photo with a different UID and without the original metadata content.
380   * 
381   * After this method call the UID will be invalid and feedback tasks will be generated and submitted to back-ends notifying the deletion of the photo.
382   * 
383   * This method will in general ignore non-existent UIDs, if provided, but will give an error on permission problem.
384   * 
385   * <h2>Example Query:</h2>
386   *
387   * DELETE /rest/{@value service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT}/{@value service.tut.pori.contentanalysis.Definitions#METHOD_DELETE_PHOTO_METADATA}?{@value service.tut.pori.contentanalysis.Definitions#PARAMETER_GUID}=0<br>
388   *
389   * <h2>Example Result:</h2>
390   * 
391   * {@doc.restlet service="[service.tut.pori.contentanalysis.reference.Definitions#SERVICE_CA_REFERENCE_CLIENT]" method="[service.tut.pori.contentanalysis.Definitions#METHOD_DELETE_PHOTO_METADATA]" type="DELETE" query="[service.tut.pori.contentanalysis.Definitions#PARAMETER_GUID]=0" body_uri=""}
392   * 
393   * @param authenticatedUser  Note: this method requires authentication, but for the reference implementation, anonymous access is granted.
394   * @param guid One or more photo GUIDs for deletion.
395   * @return response
396   */
397  @HTTPServiceMethod(name = Definitions.METHOD_DELETE_PHOTO_METADATA, acceptedMethods={core.tut.pori.http.Definitions.METHOD_DELETE})
398  public Response deletePhotos(
399      @HTTPAuthenticationParameter(required=false) AuthenticationParameter authenticatedUser,
400      @HTTPMethodParameter(name = Definitions.PARAMETER_GUID) StringParameter guid
401      )
402  {
403    CAReferenceCore.deletePhotos(authenticatedUser.getUserIdentity(), guid.getValues());
404    return new Response();
405  }
406}