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.Response.Status;
026import core.tut.pori.http.annotations.HTTPAuthenticationParameter;
027import core.tut.pori.http.annotations.HTTPMethodParameter;
028import core.tut.pori.http.annotations.HTTPService;
029import core.tut.pori.http.annotations.HTTPServiceMethod;
030import core.tut.pori.http.parameters.AuthenticationParameter;
031import core.tut.pori.http.parameters.DataGroups;
032import core.tut.pori.http.parameters.DateIntervalParameter;
033import core.tut.pori.http.parameters.InputStreamParameter;
034import core.tut.pori.http.parameters.Limits;
035import core.tut.pori.http.parameters.LongParameter;
036import core.tut.pori.http.parameters.StringParameter;
037import core.tut.pori.utils.XMLFormatter;
038import service.tut.pori.apilta.sensors.datatypes.SensorTask;
039import service.tut.pori.tasks.datatypes.Task;
040import service.tut.pori.tasks.datatypes.TaskList;
041
042/**
043 * Reference implementation for client API methods.
044 * 
045 * <h1>Implementation Service path {@value service.tut.pori.apilta.sensors.Definitions#SERVICE_SENSORS}</h1>
046 * 
047 * @see service.tut.pori.apilta.sensors.SensorService
048 *
049 */
050@HTTPService(name = Definitions.SERVICE_SENSORS_REFERENCE_CLIENT)
051public class ClientService {
052  private static final Logger LOGGER = Logger.getLogger(ClientService.class);
053  private XMLFormatter _formatter = new XMLFormatter();
054  
055  /**
056   * 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".
057   * 
058   * <h2>Example Query:</h2>
059   *
060   * POST /rest/{@value service.tut.pori.apilta.sensors.reference.Definitions#SERVICE_SENSORS_REFERENCE_CLIENT}/{@value service.tut.pori.apilta.sensors.Definitions#METHOD_CREATE_TASK}<br>
061   * Content-Type: text/xml; charset=UTF-8<br><br>
062   *
063   * <b>[HTTP BODY STARTS]</b><br>
064   * 
065   * {@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>
066   * 
067   * <b>[HTTP BODY ENDS]</b><br>
068   *
069   * <h2>Example Result:</h2>
070   * 
071   * {@doc.restlet service="[service.tut.pori.apilta.sensors.reference.Definitions#SERVICE_SENSORS_REFERENCE_CLIENT]" method="[service.tut.pori.apilta.sensors.Definitions#METHOD_CREATE_TASK]" type="POST" query="" body_uri="[service.tut.pori.apilta.sensors.reference.Definitions#SERVICE_SENSORS_REFERENCE_EXAMPLE]/[service.tut.pori.tasks.Definitions#ELEMENT_TASK]"}
072   * 
073   * @param authenticatedUser 
074   * @param xml Only the workload data should be in the body. See {@link service.tut.pori.apilta.sensors.datatypes.SensorTask}
075   * @return {@link service.tut.pori.tasks.datatypes.TaskList} with identifier for the generated task
076   */
077  @HTTPServiceMethod(name = service.tut.pori.apilta.sensors.Definitions.METHOD_CREATE_TASK, acceptedMethods={core.tut.pori.http.Definitions.METHOD_POST})
078  public Response createTask (
079      @HTTPAuthenticationParameter(required = false) AuthenticationParameter authenticatedUser,
080      @HTTPMethodParameter(name = InputStreamParameter.PARAMETER_DEFAULT_NAME, bodyParameter = true) InputStreamParameter xml
081      ) 
082  {
083    try {
084      String body = IOUtils.toString(xml.getValue(), core.tut.pori.http.Definitions.CHARSET_UTF8); // read the body
085      LOGGER.debug(body); // print to debug
086      try(InputStream input = IOUtils.toInputStream(body, core.tut.pori.http.Definitions.CHARSET_UTF8)){ // convert back to stream for unmarshal
087        String taskId = SensorsReferenceCore.createTask(authenticatedUser.getUserIdentity(), _formatter.toObject(input, SensorTask.class));
088        TaskList taskList = new TaskList();
089        Task task = new SensorTask();
090        task.addTaskId(taskId);
091        taskList.addTask(task);
092        return new Response(taskList);
093      }
094    } catch (IOException ex) {
095      LOGGER.error(ex, ex);
096      return new Response(Status.BAD_REQUEST);
097    }
098  }
099  
100  /**
101   * 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".
102   * 
103   * <h2>Example Query:</h2>
104   *
105   * POST /rest/{@value service.tut.pori.apilta.sensors.reference.Definitions#SERVICE_SENSORS_REFERENCE_CLIENT}/{@value service.tut.pori.apilta.sensors.Definitions#METHOD_MODIFY_TASK}<br>
106   * Content-Type: text/xml; charset=UTF-8<br><br>
107   *
108   * <b>[HTTP BODY STARTS]</b><br>
109   * 
110   * {@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>
111   * 
112   * <b>[HTTP BODY ENDS]</b><br>
113   *
114   * <h2>Example Result:</h2>
115   * 
116   * {@doc.restlet service="[service.tut.pori.apilta.sensors.reference.Definitions#SERVICE_SENSORS_REFERENCE_CLIENT]" method="[service.tut.pori.apilta.sensors.Definitions#METHOD_MODIFY_TASK]" type="POST" query="" body_uri="[service.tut.pori.apilta.sensors.reference.Definitions#SERVICE_SENSORS_REFERENCE_EXAMPLE]/[service.tut.pori.tasks.Definitions#ELEMENT_TASK]"}
117   * 
118   * @param authenticatedUser 
119   * @param xml Only the workload data should be in the body. See {@link service.tut.pori.apilta.sensors.datatypes.SensorTask}
120   * @return {@link service.tut.pori.tasks.datatypes.TaskList} with identifier for the generated task
121   */
122  @HTTPServiceMethod(name = service.tut.pori.apilta.sensors.Definitions.METHOD_MODIFY_TASK, acceptedMethods={core.tut.pori.http.Definitions.METHOD_POST})
123  public Response modifyTask (
124      @HTTPAuthenticationParameter(required = false) AuthenticationParameter authenticatedUser,
125      @HTTPMethodParameter(name = InputStreamParameter.PARAMETER_DEFAULT_NAME, bodyParameter = true) InputStreamParameter xml
126      ) 
127  {
128    try {
129      String body = IOUtils.toString(xml.getValue(), core.tut.pori.http.Definitions.CHARSET_UTF8); // read the body
130      LOGGER.debug(body); // print to debug
131      try(InputStream input = IOUtils.toInputStream(body, core.tut.pori.http.Definitions.CHARSET_UTF8)){ // convert back to stream for unmarshal
132        String taskId = SensorsReferenceCore.modifyTask(authenticatedUser.getUserIdentity(), _formatter.toObject(input, SensorTask.class));
133        TaskList taskList = new TaskList();
134        Task task = new SensorTask();
135        task.addTaskId(taskId);
136        taskList.addTask(task);
137        return new Response(taskList);
138      }
139    } catch (IOException ex) {
140      LOGGER.error(ex, ex);
141      return new Response(Status.BAD_REQUEST);
142    }
143  }
144  
145  /**
146   * This method can be used to retrieve measurements for a single task or for a list of tasks defined by the task ids.
147   * 
148   * <h2>Example Query:</h2>
149   *
150   * GET /rest/{@value service.tut.pori.apilta.sensors.reference.Definitions#SERVICE_SENSORS_REFERENCE_CLIENT}/{@value service.tut.pori.apilta.sensors.Definitions#METHOD_GET_MEASUREMENTS}?{@value service.tut.pori.tasks.Definitions#PARAMETER_TASK_ID}=1<br>
151   *
152   * <h2>Example Result:</h2>
153   * 
154   * {@doc.restlet service="[service.tut.pori.apilta.sensors.reference.Definitions#SERVICE_SENSORS_REFERENCE_CLIENT]" method="[service.tut.pori.apilta.sensors.Definitions#METHOD_GET_MEASUREMENTS]" type="GET" query="[service.tut.pori.tasks.Definitions#PARAMETER_TASK_ID]=1" body_uri=""}
155   * 
156   * 
157   * @param authenticatedUser
158   * @param taskId
159   * @param backendIdFilter
160   * @param createdFilter
161   * @param dataGroups 
162   * @param limits
163   * @param measurementIdFilter
164   * @return see {@link service.tut.pori.apilta.sensors.datatypes.MeasurementList}
165   */
166  @HTTPServiceMethod(name = service.tut.pori.apilta.sensors.Definitions.METHOD_GET_MEASUREMENTS, acceptedMethods={core.tut.pori.http.Definitions.METHOD_GET})
167  public Response getMeasurements(
168      @HTTPAuthenticationParameter(required = false) AuthenticationParameter authenticatedUser,
169      @HTTPMethodParameter(name = service.tut.pori.tasks.Definitions.PARAMETER_TASK_ID) StringParameter taskId,
170      @HTTPMethodParameter(name = service.tut.pori.tasks.Definitions.PARAMETER_BACKEND_ID, required = false) LongParameter backendIdFilter,
171      @HTTPMethodParameter(name = service.tut.pori.tasks.Definitions.PARAMETER_CREATED, required = false) DateIntervalParameter createdFilter,
172      @HTTPMethodParameter(name = DataGroups.PARAMETER_DEFAULT_NAME, required = false) DataGroups dataGroups,
173      @HTTPMethodParameter(name = Limits.PARAMETER_DEFAULT_NAME, required = false) Limits limits,
174      @HTTPMethodParameter(name = service.tut.pori.apilta.sensors.Definitions.PARAMETER_MEASUREMENT_ID, required = false) StringParameter measurementIdFilter
175      )
176  {
177    return new Response(SensorsReferenceCore.getMeasurements(authenticatedUser.getUserIdentity(), backendIdFilter.getValues(), createdFilter.getValues(), dataGroups, limits, measurementIdFilter.getValues(), taskId.getValues()));
178  }
179}