001/**
002 * Copyright 2016 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.apilta.sensors.reference;
017
018import java.io.IOException;
019import java.io.InputStream;
020
021import org.apache.commons.io.IOUtils;
022import org.apache.log4j.Logger;
023
024import core.tut.pori.http.Response;
025import core.tut.pori.http.annotations.HTTPAuthenticationParameter;
026import core.tut.pori.http.annotations.HTTPMethodParameter;
027import core.tut.pori.http.annotations.HTTPService;
028import core.tut.pori.http.annotations.HTTPServiceMethod;
029import core.tut.pori.http.parameters.AuthenticationParameter;
030import core.tut.pori.http.parameters.DataGroups;
031import core.tut.pori.http.parameters.InputStreamParameter;
032import core.tut.pori.http.parameters.Limits;
033import core.tut.pori.http.parameters.StringParameter;
034import core.tut.pori.utils.XMLFormatter;
035import service.tut.pori.apilta.sensors.datatypes.SensorTask;
036
037/**
038 * 
039 * Reference implementation for Back-end APIs
040 *
041 */
042@HTTPService(name = Definitions.SERVICE_SENSORS_REFERENCE_BACKEND)
043public class BackendService {
044  private static final Logger LOGGER = Logger.getLogger(BackendService.class);
045  private XMLFormatter _formatter = new XMLFormatter();
046  
047  /**
048   * 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".
049   * 
050   * <h2>Example Query:</h2>
051   *
052   * POST /rest/{@value service.tut.pori.apilta.sensors.reference.Definitions#SERVICE_SENSORS_REFERENCE_BACKEND}/{@value service.tut.pori.tasks.Definitions#METHOD_ADD_TASK}<br>
053   * Content-Type: text/xml; charset=UTF-8<br><br>
054   *
055   * <b>[HTTP BODY STARTS]</b><br>
056   * 
057   * {@doc.restlet service="[service.tut.pori.apilta.sensors.reference.Definitions#SERVICE_SENSORS_REFERENCE_EXAMPLE]" method="[service.tut.pori.tasks.Definitions#ELEMENT_TASK]" type="GET" query="" body_uri=""} <br>
058   * 
059   * <b>[HTTP BODY ENDS]</b><br>
060   *
061   * <h2>Example Result:</h2>
062   * 
063   * {@doc.restlet service="[service.tut.pori.apilta.sensors.reference.Definitions#SERVICE_SENSORS_REFERENCE_BACKEND]" method="[service.tut.pori.tasks.Definitions#METHOD_ADD_TASK]" type="POST" query="" body_uri="[service.tut.pori.apilta.sensors.reference.Definitions#SERVICE_SENSORS_REFERENCE_EXAMPLE]/[service.tut.pori.tasks.Definitions#ELEMENT_TASK]"}
064   * 
065   * @param authenticatedUser 
066   * @param xml Only the workload data should be in the body. See {@link service.tut.pori.apilta.sensors.datatypes.SensorTask}
067   */
068  @HTTPServiceMethod(name = service.tut.pori.tasks.Definitions.METHOD_ADD_TASK, acceptedMethods={core.tut.pori.http.Definitions.METHOD_POST})
069  public void addTask (
070      @HTTPAuthenticationParameter(required = false) AuthenticationParameter authenticatedUser,
071      @HTTPMethodParameter(name = InputStreamParameter.PARAMETER_DEFAULT_NAME, bodyParameter = true) InputStreamParameter xml
072      ) 
073  {
074    try {
075      String body = IOUtils.toString(xml.getValue(), core.tut.pori.http.Definitions.CHARSET_UTF8); // read the body
076      LOGGER.debug(body); // print to debug
077      try(InputStream input = IOUtils.toInputStream(body, core.tut.pori.http.Definitions.CHARSET_UTF8)){ // convert back to stream for unmarshal
078        SensorsReferenceCore.addTask(authenticatedUser.getUserIdentity(), _formatter.toObject(input, SensorTask.class));
079      }
080    } catch (IOException ex) {
081      LOGGER.error(ex, ex);
082    }
083  }
084  
085  /**
086   * This method can be used to query the current status of a sensor task from the back-end.
087   * 
088   * 
089   * <h2>Example Query:</h2>
090   *
091   * GET /rest/{@value service.tut.pori.apilta.sensors.reference.Definitions#SERVICE_SENSORS_REFERENCE_BACKEND}/{@value service.tut.pori.tasks.Definitions#METHOD_QUERY_TASK_STATUS}?{@value service.tut.pori.tasks.Definitions#PARAMETER_TASK_ID}=1<br>
092   *
093   * <h2>Example Result:</h2>
094   * 
095   * {@doc.restlet service="[service.tut.pori.apilta.sensors.reference.Definitions#SERVICE_SENSORS_REFERENCE_BACKEND]" method="[service.tut.pori.tasks.Definitions#METHOD_QUERY_TASK_STATUS]" type="GET" query="[service.tut.pori.tasks.Definitions#PARAMETER_TASK_ID]=1" body_uri=""}
096   * 
097   * @param authenticatedUser 
098   * @param taskId
099   * @param dataGroups
100   * @param limits paging limits
101   * @return See {@link service.tut.pori.apilta.sensors.datatypes.SensorTask}
102   */
103  @HTTPServiceMethod(name = service.tut.pori.tasks.Definitions.METHOD_QUERY_TASK_STATUS, acceptedMethods={core.tut.pori.http.Definitions.METHOD_GET})
104  public Response queryTaskStatus(
105      @HTTPAuthenticationParameter(required = false) AuthenticationParameter authenticatedUser,
106      @HTTPMethodParameter(name = service.tut.pori.tasks.Definitions.PARAMETER_TASK_ID) StringParameter taskId,
107      @HTTPMethodParameter(name = DataGroups.PARAMETER_DEFAULT_NAME, required = false) DataGroups dataGroups,
108      @HTTPMethodParameter(name = Limits.PARAMETER_DEFAULT_NAME, required = false) Limits limits
109      )
110  {
111    return new Response(SensorsReferenceCore.generateTaskResults(authenticatedUser.getUserIdentity(), dataGroups, limits, taskId.getValue(), service.tut.pori.apilta.sensors.Definitions.TASK_TYPE_DATA_COLLECT)); // we can simply return pseudo randomly generated task results with hard-coded task type
112  }
113}