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.alerts.reference;
017
018import java.io.IOException;
019import java.io.InputStream;
020import java.util.ArrayList;
021
022import org.apache.commons.io.IOUtils;
023import org.apache.log4j.Logger;
024
025import core.tut.pori.http.Response;
026import core.tut.pori.http.Response.Status;
027import core.tut.pori.http.annotations.HTTPAuthenticationParameter;
028import core.tut.pori.http.annotations.HTTPMethodParameter;
029import core.tut.pori.http.annotations.HTTPService;
030import core.tut.pori.http.annotations.HTTPServiceMethod;
031import core.tut.pori.http.parameters.AuthenticationParameter;
032import core.tut.pori.http.parameters.DataGroups;
033import core.tut.pori.http.parameters.DateIntervalParameter;
034import core.tut.pori.http.parameters.DoubleParameter;
035import core.tut.pori.http.parameters.InputStreamParameter;
036import core.tut.pori.http.parameters.Limits;
037import core.tut.pori.http.parameters.LongParameter;
038import core.tut.pori.http.parameters.StringParameter;
039import core.tut.pori.utils.XMLFormatter;
040import service.tut.pori.apilta.alerts.datatypes.Alert;
041import service.tut.pori.apilta.alerts.datatypes.AlertList;
042import service.tut.pori.apilta.alerts.datatypes.LocationParameter;
043import service.tut.pori.apilta.files.datatypes.FileDetails;
044import service.tut.pori.apilta.files.datatypes.FileDetailsList;
045
046/**
047 * Reference implementation for client API methods.
048 * 
049 * <h1>Implementation Service path {@value service.tut.pori.apilta.alerts.Definitions#SERVICE_ALERTS}</h1>
050 * 
051 * @see service.tut.pori.apilta.alerts.AlertService
052 *
053 */
054@HTTPService(name = Definitions.SERVICE_ALERTS_REFERENCE_CLIENT)
055public class ClientService {
056  private static final Logger LOGGER = Logger.getLogger(ClientService.class);
057  private XMLFormatter _formatter = new XMLFormatter();
058  
059  /**
060   * This method can be used to retrieve alerts based on the given filters
061   * 
062   * <h2>Example Query:</h2>
063   *
064   * GET /rest/{@value service.tut.pori.apilta.alerts.reference.Definitions#SERVICE_ALERTS_REFERENCE_CLIENT}/{@value service.tut.pori.apilta.alerts.Definitions#METHOD_GET_ALERTS}?{@value service.tut.pori.apilta.alerts.Definitions#PARAMETER_ALERT_GROUP_ID}=1<br>
065   *
066   * <h2>Example Result:</h2>
067   * 
068   * {@doc.restlet service="[service.tut.pori.apilta.alerts.reference.Definitions#SERVICE_ALERTS_REFERENCE_CLIENT]" method="[service.tut.pori.apilta.alerts.Definitions#METHOD_GET_ALERTS]" type="GET" query="[service.tut.pori.apilta.alerts.Definitions#PARAMETER_ALERT_GROUP_ID]=1" body_uri=""}
069   * 
070   * Either alertGroupIdFilter or location must be given. Range cannot be given without location.
071   * 
072   * @param authenticatedUser
073   * @param alertGroupIdFilter
074   * @param alertTypeFilter
075   * @param createdFilter 
076   * @param dataGroups valid groups are {@value DataGroups#DATA_GROUP_BASIC} (default) and {@value DataGroups#DATA_GROUP_ALL}. The basic group does not contain file details or other optional elements.
077   * @param location
078   * @param range in km, if not given, the default range is used ({@link service.tut.pori.apilta.alerts.Definitions#DEFAULT_RANGE})
079   * @param limits
080   * @return see {@link service.tut.pori.apilta.alerts.datatypes.AlertList}
081   */
082  @HTTPServiceMethod(name = service.tut.pori.apilta.alerts.Definitions.METHOD_GET_ALERTS, acceptedMethods={core.tut.pori.http.Definitions.METHOD_GET})
083  public Response getAlerts(
084      @HTTPAuthenticationParameter(required = false) AuthenticationParameter authenticatedUser,
085      @HTTPMethodParameter(name = service.tut.pori.apilta.alerts.Definitions.PARAMETER_ALERT_GROUP_ID, required = false) LongParameter alertGroupIdFilter,
086      @HTTPMethodParameter(name = service.tut.pori.apilta.alerts.Definitions.PARAMETER_ALERT_TYPE, required = false) StringParameter alertTypeFilter,
087      @HTTPMethodParameter(name = service.tut.pori.apilta.alerts.Definitions.PARAMETER_CREATED, required = false) DateIntervalParameter createdFilter,
088      @HTTPMethodParameter(name = DataGroups.PARAMETER_DEFAULT_NAME, required = false) DataGroups dataGroups,
089      @HTTPMethodParameter(name = LocationParameter.PARAMETER_DEFAULT_NAME, required = false) LocationParameter location,
090      @HTTPMethodParameter(name = service.tut.pori.apilta.alerts.Definitions.PARAMETER_RANGE, required = false) DoubleParameter range,
091      @HTTPMethodParameter(name = Limits.PARAMETER_DEFAULT_NAME, required = false) Limits limits
092      )
093  {
094    return new Response(AlertsReferenceCore.retrieveAlerts(alertGroupIdFilter.getValues(), alertTypeFilter.getValues(), authenticatedUser.getUserIdentity(), createdFilter.getValues(), dataGroups, location.getValue(), range.getValue(), limits));
095  }
096
097  /**
098   * 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".
099   * 
100   * <h2>Example Query:</h2>
101   *
102   * POST /rest/{@value service.tut.pori.apilta.alerts.reference.Definitions#SERVICE_ALERTS_REFERENCE_CLIENT}/{@value service.tut.pori.apilta.alerts.Definitions#METHOD_ADD_ALERT}?{@value service.tut.pori.apilta.alerts.Definitions#PARAMETER_ALERT_GROUP_ID}=1<br>
103   * Content-Type: text/xml; charset=UTF-8<br><br>
104   *
105   * <b>[HTTP BODY STARTS]</b><br>
106   * 
107   * {@doc.restlet service="[service.tut.pori.apilta.alerts.reference.Definitions#SERVICE_ALERTS_REFERENCE_EXAMPLE]" method="[service.tut.pori.apilta.alerts.datatypes.Definitions#ELEMENT_ALERT]" type="GET" query="" body_uri=""} <br>
108   * 
109   * <b>[HTTP BODY ENDS]</b><br>
110   *
111   * <h2>Example Result:</h2>
112   * 
113   * {@doc.restlet service="[service.tut.pori.apilta.alerts.reference.Definitions#SERVICE_ALERTS_REFERENCE_CLIENT]" method="[service.tut.pori.apilta.alerts.Definitions#METHOD_ADD_ALERT]" type="POST" query="[service.tut.pori.apilta.alerts.Definitions#PARAMETER_ALERT_GROUP_ID]=1" body_uri="[service.tut.pori.apilta.alerts.reference.Definitions#SERVICE_ALERTS_REFERENCE_EXAMPLE]/[service.tut.pori.apilta.alerts.datatypes.Definitions#ELEMENT_ALERT]"}
114   * 
115   * 
116   * @param authenticatedUser
117   * @param alertGroupId the group which the alert should be associated with
118   * @param xml Only the workload data should be in the body. See {@link service.tut.pori.apilta.alerts.datatypes.Alert}
119   * @return response See {@link service.tut.pori.apilta.alerts.datatypes.AlertList}
120   */
121  @HTTPServiceMethod(name = service.tut.pori.apilta.alerts.Definitions.METHOD_ADD_ALERT, acceptedMethods={core.tut.pori.http.Definitions.METHOD_POST})
122  public Response addAlert (
123      @HTTPAuthenticationParameter(required = false) AuthenticationParameter authenticatedUser,
124      @HTTPMethodParameter(name = service.tut.pori.apilta.alerts.Definitions.PARAMETER_ALERT_GROUP_ID) LongParameter alertGroupId,
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 alertId = AlertsReferenceCore.addAlert(_formatter.toObject(input, Alert.class), alertGroupId.getValues(), authenticatedUser.getUserIdentity());
133        AlertList alerts = new AlertList();
134        ArrayList<Alert> list = new ArrayList<>(1);
135        alerts.setAlerts(list);
136        Alert alert = new Alert();
137        alert.setAlertId(alertId);
138        list.add(alert);
139        return new Response(alerts);
140      }
141    } catch (IOException ex) {
142      LOGGER.error(ex, ex);
143      return new Response(Status.BAD_REQUEST);
144    }
145  }
146  
147  /**
148   * The request is to be sent in the body of POST method.
149   * 
150   * <h2>Example Query:</h2>
151   *
152   * POST /rest/{@value service.tut.pori.apilta.alerts.reference.Definitions#SERVICE_ALERTS_REFERENCE_CLIENT}/{@value service.tut.pori.apilta.alerts.Definitions#METHOD_CREATE_FILE}<br>
153   * Content-Type: text/xml; charset=UTF-8<br><br>
154   *
155   * <b>[HTTP BODY STARTS]</b><br>
156   * 
157   * [ANY FILE CONTENT] <br>
158   * 
159   * <b>[HTTP BODY ENDS]</b><br>
160   *
161   * <h2>Example Result:</h2>
162   * 
163   * {@doc.restlet service="[service.tut.pori.apilta.alerts.reference.Definitions#SERVICE_ALERTS_REFERENCE_CLIENT]" method="[service.tut.pori.apilta.alerts.Definitions#METHOD_CREATE_FILE]" type="POST" query="" body_uri="[service.tut.pori.apilta.alerts.reference.Definitions#SERVICE_ALERTS_REFERENCE_EXAMPLE]/[service.tut.pori.apilta.alerts.datatypes.Definitions#ELEMENT_ALERT]"}
164   * 
165   * @param authenticatedUser
166   * @param file only the file contents should be in the body.
167   * @return {@link service.tut.pori.apilta.files.datatypes.FileDetailsList} with identifier for the generated file
168   */
169  @HTTPServiceMethod(name = service.tut.pori.apilta.alerts.Definitions.METHOD_CREATE_FILE, acceptedMethods={core.tut.pori.http.Definitions.METHOD_POST})
170  public Response createFile (
171      @HTTPAuthenticationParameter(required = false) AuthenticationParameter authenticatedUser,
172      @HTTPMethodParameter(name = InputStreamParameter.PARAMETER_DEFAULT_NAME, bodyParameter = true) InputStreamParameter file
173      ) 
174  {
175    FileDetailsList list = new FileDetailsList();
176    FileDetails details = new FileDetails();
177    details.setGUID(AlertsReferenceCore.createFile(authenticatedUser.getUserIdentity(), file.getValue()));
178    list.addFile(details);
179    return new Response(list);
180  }
181}