raimund@488: /* Copyright (C) 2013 by Bundesamt fuer Strahlenschutz raimund@488: * Software engineering by Intevation GmbH raimund@488: * rrenkert@628: * This file is Free Software under the GNU GPL (v>=3) rrenkert@628: * and comes with ABSOLUTELY NO WARRANTY! Check out rrenkert@628: * the documentation coming with IMIS-Labordaten-Application for details. raimund@488: */ raimund@488: package de.intevation.lada.rest; raimund@488: raimund@787: import java.util.List; raimund@787: raimund@488: import javax.enterprise.context.RequestScoped; raimund@488: import javax.inject.Inject; raimund@582: import javax.servlet.http.HttpServletRequest; raimund@488: import javax.ws.rs.DELETE; raimund@488: import javax.ws.rs.GET; raimund@488: import javax.ws.rs.POST; raimund@488: import javax.ws.rs.PUT; raimund@488: import javax.ws.rs.Path; raimund@488: import javax.ws.rs.PathParam; raimund@488: import javax.ws.rs.Produces; raimund@488: import javax.ws.rs.core.Context; raimund@488: import javax.ws.rs.core.HttpHeaders; raimund@488: import javax.ws.rs.core.MediaType; raimund@488: import javax.ws.rs.core.MultivaluedMap; raimund@488: import javax.ws.rs.core.UriInfo; raimund@488: raimund@787: import org.apache.log4j.Logger; raimund@787: raimund@595: import de.intevation.lada.lock.LockConfig; raimund@595: import de.intevation.lada.lock.LockType; raimund@595: import de.intevation.lada.lock.ObjectLocker; raimund@747: import de.intevation.lada.model.land.LMessung; raimund@745: import de.intevation.lada.model.land.LStatusProtokoll; raimund@488: import de.intevation.lada.util.annotation.AuthorizationConfig; raimund@488: import de.intevation.lada.util.annotation.RepositoryConfig; raimund@488: import de.intevation.lada.util.auth.Authorization; raimund@488: import de.intevation.lada.util.auth.AuthorizationType; raimund@774: import de.intevation.lada.util.auth.UserInfo; raimund@488: import de.intevation.lada.util.data.QueryBuilder; raimund@488: import de.intevation.lada.util.data.Repository; raimund@488: import de.intevation.lada.util.data.RepositoryType; raimund@582: import de.intevation.lada.util.rest.RequestMethod; raimund@488: import de.intevation.lada.util.rest.Response; raimund@787: import de.intevation.lada.validation.Validator; raimund@787: import de.intevation.lada.validation.Violation; raimund@787: import de.intevation.lada.validation.annotation.ValidationConfig; raimund@488: rrenkert@628: /** rrenkert@628: * REST service for Status objects. rrenkert@628: *
rrenkert@628: * The services produce data in the application/json media type. rrenkert@628: * All HTTP methods use the authorization module to determine if the user is rrenkert@628: * allowed to perform the requested action. rrenkert@628: * A typical response holds information about the action performed and the data. rrenkert@628: *
rrenkert@628: *
rrenkert@628: * {
rrenkert@628: * "success": [boolean];
rrenkert@628: * "message": [string],
rrenkert@628: * "data":[{
rrenkert@628: * "id": [number],
rrenkert@628: * "erzeuger": [string],
rrenkert@628: * "messungsId": [number],
rrenkert@628: * "status": [number],
rrenkert@628: * "owner": [boolean],
rrenkert@628: * "readonly": [boolean],
rrenkert@628: * "treeModified": [timestamp],
rrenkert@628: * "parentModified": [timestamp],
rrenkert@628: * "sdatum": [timestamp],
rrenkert@628: * "skommentar": [string]
rrenkert@628: * }],
rrenkert@628: * "errors": [object],
rrenkert@628: * "warnings": [object],
rrenkert@628: * "readonly": [boolean],
rrenkert@628: * "totalCount": [number]
rrenkert@628: * }
rrenkert@628: *
rrenkert@628: *
rrenkert@628: *
rrenkert@628: * @author Raimund Renkert
rrenkert@628: */
raimund@488: @Path("status")
raimund@488: @RequestScoped
raimund@488: public class StatusService {
raimund@488:
raimund@787: @Inject
raimund@787: private Logger logger = Logger.getLogger(StatusService.class);
raimund@787:
rrenkert@628: /**
rrenkert@628: * The data repository granting read/write access.
rrenkert@628: */
raimund@488: @Inject
raimund@488: @RepositoryConfig(type=RepositoryType.RW)
raimund@488: private Repository defaultRepo;
raimund@488:
rrenkert@628: /**
rrenkert@628: * The object lock mechanism.
rrenkert@628: */
raimund@595: @Inject
raimund@595: @LockConfig(type=LockType.TIMESTAMP)
raimund@595: private ObjectLocker lock;
raimund@595:
rrenkert@628: /**
rrenkert@628: * The authorization module.
rrenkert@628: */
raimund@488: @Inject
raimund@722: @AuthorizationConfig(type=AuthorizationType.HEADER)
raimund@488: private Authorization authorization;
raimund@488:
raimund@787: @Inject
raimund@787: @ValidationConfig(type="Status")
raimund@787: private Validator validator;
raimund@787:
raimund@488: /**
rrenkert@628: * Get all Status objects.
rrenkert@628: * rrenkert@628: * The requested objects can be filtered using a URL parameter named raimund@711: * messungsId. rrenkert@628: *
rrenkert@628: * Example: http://example.com/status?messungsId=[ID]
raimund@488: *
rrenkert@628: * @return Response object containing all Status objects.
raimund@488: */
raimund@488: @GET
raimund@488: @Path("/")
raimund@488: @Produces(MediaType.APPLICATION_JSON)
raimund@488: public Response get(
raimund@488: @Context HttpHeaders headers,
raimund@582: @Context UriInfo info,
raimund@582: @Context HttpServletRequest request
raimund@488: ) {
raimund@488: MultivaluedMap
rrenkert@628: * The id is appended to the URL as a path parameter.
rrenkert@628: *
rrenkert@628: * Example: http://example.com/status/{id}
raimund@488: *
rrenkert@628: * @return Response object containing a single Status.
raimund@488: */
raimund@488: @GET
raimund@488: @Path("/{id}")
raimund@488: @Produces(MediaType.APPLICATION_JSON)
raimund@488: public Response getById(
raimund@488: @Context HttpHeaders headers,
raimund@582: @Context HttpServletRequest request,
raimund@488: @PathParam("id") String id
raimund@488: ) {
raimund@787: Response response = defaultRepo.getById(
raimund@787: LStatusProtokoll.class,
raimund@787: Integer.valueOf(id),
raimund@787: "land");
raimund@787: LStatusProtokoll status = (LStatusProtokoll)response.getData();
raimund@787: Violation violation = validator.validate(status);
raimund@787: if (violation.hasErrors() || violation.hasWarnings()) {
raimund@787: response.setErrors(violation.getErrors());
raimund@787: response.setWarnings(violation.getWarnings());
raimund@787: }
raimund@787:
raimund@582: return authorization.filter(
raimund@582: request,
raimund@787: response,
raimund@745: LStatusProtokoll.class);
raimund@488: }
raimund@488:
rrenkert@628: /**
rrenkert@628: * Create a Status object.
rrenkert@628: *
rrenkert@628: * The new object is embedded in the post data as JSON formatted string.
rrenkert@628: *
rrenkert@628: *
rrenkert@628: * The object to update should come as JSON formatted string.
rrenkert@628: *
rrenkert@628: * The id is appended to the URL as a path parameter.
rrenkert@628: *
rrenkert@628: * Example: http://example.com/status/{id}
raimund@488: *
raimund@488: * @return Response object.
raimund@488: */
raimund@488: @DELETE
raimund@488: @Path("/{id}")
raimund@488: @Produces(MediaType.APPLICATION_JSON)
raimund@488: public Response delete(
raimund@488: @Context HttpHeaders headers,
raimund@582: @Context HttpServletRequest request,
raimund@488: @PathParam("id") String id
raimund@488: ) {
raimund@488: /* Get the object by id*/
raimund@488: Response object =
raimund@745: defaultRepo.getById(LStatusProtokoll.class, Integer.valueOf(id), "land");
raimund@745: LStatusProtokoll obj = (LStatusProtokoll)object.getData();
raimund@582: if (!authorization.isAuthorized(
raimund@582: request,
raimund@582: obj,
raimund@582: RequestMethod.DELETE,
raimund@745: LStatusProtokoll.class)
raimund@582: ) {
raimund@582: return new Response(false, 699, null);
raimund@582: }
raimund@595: if (lock.isLocked(obj)) {
raimund@595: return new Response(false, 697, null);
raimund@595: }
raimund@488: /* Delete the object*/
raimund@488: return defaultRepo.delete(obj, "land");
raimund@488: }
raimund@488: }
rrenkert@628: *
rrenkert@628: *
rrenkert@628: * @return A response object containing the created Status.
rrenkert@628: */
raimund@488: @POST
raimund@488: @Path("/")
raimund@488: @Produces(MediaType.APPLICATION_JSON)
raimund@488: public Response create(
raimund@488: @Context HttpHeaders headers,
raimund@582: @Context HttpServletRequest request,
raimund@745: LStatusProtokoll status
raimund@488: ) {
raimund@582: if (!authorization.isAuthorized(
raimund@582: request,
raimund@582: status,
raimund@582: RequestMethod.POST,
raimund@745: LStatusProtokoll.class)
raimund@582: ) {
raimund@488: return new Response(false, 699, null);
raimund@488: }
raimund@774: UserInfo userInfo = authorization.getInfo(request);
raimund@774: LMessung messung = defaultRepo.getByIdPlain(
raimund@774: LMessung.class, status.getMessungsId(), "land");
raimund@774: boolean next = false;
raimund@774: boolean change = false;
raimund@778: if (messung.getStatus() == null) {
raimund@774: status.setStatusStufe(1);
raimund@774: }
raimund@774: else {
raimund@778: LStatusProtokoll currentStatus = defaultRepo.getByIdPlain(
raimund@778: LStatusProtokoll.class, messung.getStatus(), "land");
raimund@778: for (int i = 0; i < userInfo.getFunktionen().size(); i++) {
raimund@778: if (userInfo.getFunktionen().get(i) > currentStatus.getStatusStufe()) {
raimund@778: next = true;
raimund@778: change = false;
raimund@778: break;
raimund@778: }
raimund@778: else if (userInfo.getFunktionen().get(i) == currentStatus.getStatusStufe()) {
raimund@778: change = true;
raimund@778: }
raimund@778: }
raimund@778: if ((change || next) && status.getStatusWert() == 4) {
raimund@778: status.setStatusStufe(1);
raimund@778: }
raimund@778: else if (change) {
raimund@778: status.setStatusStufe(currentStatus.getStatusStufe());
raimund@778: }
raimund@778: else if (next) {
raimund@778: status.setStatusStufe(currentStatus.getStatusStufe() + 1);
raimund@778: }
raimund@778: else {
raimund@778: return new Response(false, 699, null);
raimund@778: }
raimund@774: }
raimund@787: Violation violation = validator.validate(status);
raimund@787: if (violation.hasErrors()) {
raimund@787: Response response = new Response(false, 604, status);
raimund@787: response.setErrors(violation.getErrors());
raimund@787: response.setWarnings(violation.getWarnings());
raimund@787: return response;
raimund@787: }
raimund@747: Response response = defaultRepo.create(status, "land");
raimund@747: LStatusProtokoll created = (LStatusProtokoll)response.getData();
raimund@747: messung.setStatus(created.getId());
raimund@747: defaultRepo.update(messung, "land");
raimund@488: /* Persist the new object*/
raimund@601: return authorization.filter(
raimund@601: request,
raimund@747: response,
raimund@745: LStatusProtokoll.class);
raimund@488: }
raimund@488:
raimund@488: /**
rrenkert@628: * Update an existing Status object.
rrenkert@628: *
rrenkert@628: * {
rrenkert@628: * "owner": [boolean],
rrenkert@628: * "messungsId": [number],
rrenkert@628: * "erzeuger": [string],
rrenkert@628: * "status": [number],
rrenkert@628: * "skommentar": [string],
rrenkert@628: * "treeModified":null,
rrenkert@628: * "parentModified":null,
rrenkert@628: * "sdatum": [date]
rrenkert@628: * }
rrenkert@628: *
rrenkert@628: *
rrenkert@628: *
raimund@488: *
rrenkert@628: * @return Response object containing the updated Status object.
raimund@488: */
raimund@488: @PUT
raimund@557: @Path("/{id}")
raimund@488: @Produces(MediaType.APPLICATION_JSON)
raimund@582: public Response update(
raimund@582: @Context HttpHeaders headers,
raimund@582: @Context HttpServletRequest request,
raimund@745: LStatusProtokoll status
raimund@582: ) {
raimund@595: if (lock.isLocked(status)) {
raimund@595: return new Response(false, 697, null);
raimund@595: }
raimund@774:
raimund@774: UserInfo userInfo = authorization.getInfo(request);
raimund@774: if (!userInfo.getMessstellen().contains(status.getErzeuger())) {
raimund@774: return new Response(false, 699, null);
raimund@774: }
raimund@774: LMessung messung = defaultRepo.getByIdPlain(
raimund@774: LMessung.class, status.getMessungsId(), "land");
raimund@777: LStatusProtokoll statusNew = new LStatusProtokoll();
raimund@777: statusNew.setDatum(status.getDatum());
raimund@777: statusNew.setErzeuger(status.getErzeuger());
raimund@777: statusNew.setMessungsId(status.getMessungsId());
raimund@777: statusNew.setStatusStufe(status.getStatusStufe());
raimund@777: statusNew.setStatusWert(status.getStatusWert());
raimund@777: statusNew.setText(status.getText());
raimund@787: Violation violation = validator.validate(statusNew);
raimund@787: if (violation.hasErrors()) {
raimund@787: Response response = new Response(false, 604, statusNew);
raimund@787: response.setErrors(violation.getErrors());
raimund@787: response.setWarnings(violation.getWarnings());
raimund@787: return response;
raimund@787: }
raimund@787:
raimund@777: Response response = defaultRepo.create(statusNew, "land");
raimund@774: LStatusProtokoll created = (LStatusProtokoll)response.getData();
raimund@774: messung.setStatus(created.getId());
raimund@774: defaultRepo.update(messung, "land");
raimund@774:
raimund@601: return authorization.filter(
raimund@601: request,
raimund@774: response,
raimund@745: LStatusProtokoll.class);
raimund@488: }
raimund@488:
raimund@488: /**
rrenkert@628: * Delete an existing Status object by id.
rrenkert@628: *
rrenkert@628: * {
rrenkert@628: * "id": [number],
rrenkert@628: * "owner": [boolean],
rrenkert@628: * "messungsId": [number],
rrenkert@628: * "erzeuger": [string],
rrenkert@628: * "status": [number],
rrenkert@628: * "skommentar": [string],
rrenkert@628: * "treeModified": [timestamp],
rrenkert@628: * "parentModified": [timestamp],
rrenkert@628: * "sdatum": [date]
rrenkert@628: * }
rrenkert@628: *
rrenkert@628: *