raimund@464: /* Copyright (C) 2013 by Bundesamt fuer Strahlenschutz raimund@464: * Software engineering by Intevation GmbH raimund@464: * raimund@627: * This file is Free Software under the GNU GPL (v>=3) raimund@627: * and comes with ABSOLUTELY NO WARRANTY! Check out raimund@627: * the documentation coming with IMIS-Labordaten-Application for details. raimund@464: */ raimund@460: package de.intevation.lada.rest; raimund@460: raimund@595: import java.sql.Timestamp; raimund@595: import java.util.Date; raimund@460: import java.util.List; raimund@460: raimund@460: import javax.enterprise.context.RequestScoped; raimund@460: import javax.inject.Inject; raimund@582: import javax.servlet.http.HttpServletRequest; raimund@460: import javax.ws.rs.DELETE; raimund@460: import javax.ws.rs.GET; raimund@460: import javax.ws.rs.POST; raimund@460: import javax.ws.rs.PUT; raimund@460: import javax.ws.rs.Path; raimund@460: import javax.ws.rs.PathParam; raimund@460: import javax.ws.rs.Produces; raimund@460: import javax.ws.rs.core.Context; raimund@460: import javax.ws.rs.core.HttpHeaders; raimund@460: import javax.ws.rs.core.MediaType; raimund@460: import javax.ws.rs.core.MultivaluedMap; raimund@460: import javax.ws.rs.core.UriInfo; raimund@460: raimund@681: import org.apache.log4j.Logger; raimund@681: 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@681: import de.intevation.lada.model.land.LKommentarM; raimund@460: import de.intevation.lada.model.land.LMessung; raimund@681: import de.intevation.lada.model.land.LMesswert; raimund@681: import de.intevation.lada.model.land.LStatus; raimund@460: import de.intevation.lada.model.land.MessungTranslation; raimund@460: import de.intevation.lada.util.annotation.AuthorizationConfig; raimund@460: import de.intevation.lada.util.annotation.RepositoryConfig; raimund@460: import de.intevation.lada.util.auth.Authorization; raimund@460: import de.intevation.lada.util.auth.AuthorizationType; raimund@460: import de.intevation.lada.util.data.QueryBuilder; raimund@460: import de.intevation.lada.util.data.Repository; raimund@460: import de.intevation.lada.util.data.RepositoryType; raimund@582: import de.intevation.lada.util.rest.RequestMethod; raimund@460: import de.intevation.lada.util.rest.Response; raimund@678: import de.intevation.lada.validation.Validator; raimund@678: import de.intevation.lada.validation.Violation; raimund@678: import de.intevation.lada.validation.annotation.ValidationConfig; raimund@460: raimund@627: /** raimund@627: * REST service for Messung objects. raimund@627: *

raimund@627: * The services produce data in the application/json media type. raimund@627: * All HTTP methods use the authorization module to determine if the user is raimund@627: * allowed to perform the requested action. raimund@627: * A typical response holds information about the action performed and the data. raimund@627: *

raimund@627:  * 
raimund@627:  * {
raimund@627:  *  "success": [boolean];
raimund@627:  *  "message": [string],
raimund@627:  *  "data":[{
raimund@627:  *      "id": [number],
raimund@627:  *      "fertig": [boolean],
raimund@627:  *      "letzteAenderung": [timestamp],
raimund@627:  *      "messdauer": [number],
raimund@627:  *      "messzeitpunkt": [timestamp],
raimund@627:  *      "mmtId": [string],
raimund@627:  *      "probeId": [number],
raimund@627:  *      "owner": [boolean],
raimund@627:  *      "readonly": [boolean],
raimund@627:  *      "nebenprobenNr": [string],
raimund@627:  *      "geplant": [boolean],
raimund@627:  *      "treeModified": [timestamp],
raimund@627:  *      "parentModified": [timestamp],
raimund@627:  *      "messungsIdAlt": [number]
raimund@627:  *  }],
raimund@627:  *  "errors": [object],
raimund@627:  *  "warnings": [object],
raimund@627:  *  "readonly": [boolean],
raimund@627:  *  "totalCount": [number]
raimund@627:  * }
raimund@627:  * 
raimund@627:  * 
raimund@627: * raimund@627: * @author Raimund Renkert raimund@627: */ raimund@460: @Path("messung") raimund@460: @RequestScoped raimund@460: public class MessungService { raimund@460: raimund@681: @Inject raimund@681: private Logger logger; raimund@681: raimund@627: /** raimund@627: * The data repository granting read/write access. raimund@627: */ raimund@460: @Inject raimund@460: @RepositoryConfig(type=RepositoryType.RW) raimund@460: private Repository defaultRepo; raimund@460: raimund@627: /** raimund@627: * The object lock mechanism. raimund@627: */ raimund@595: @Inject raimund@595: @LockConfig(type=LockType.TIMESTAMP) raimund@595: private ObjectLocker lock; raimund@595: raimund@627: /** raimund@627: * The authorization module. raimund@627: */ raimund@460: @Inject raimund@582: @AuthorizationConfig(type=AuthorizationType.OPEN_ID) raimund@460: private Authorization authorization; raimund@460: raimund@678: @Inject raimund@678: @ValidationConfig(type="Messung") raimund@678: private Validator validator; raimund@678: raimund@460: /** raimund@627: * Get all Messung objects. raimund@627: *

raimund@627: * The requested objects can be filtered using a URL parameter named raimund@627: * probeId. raimund@627: *

raimund@627: * Example: http://example.com/messung?probeId=[ID] raimund@460: * raimund@627: * @return Response object containing all Messung objects. raimund@460: */ raimund@460: @GET raimund@460: @Path("/") raimund@460: @Produces(MediaType.APPLICATION_JSON) raimund@460: public Response get( raimund@460: @Context HttpHeaders headers, raimund@582: @Context UriInfo info, raimund@582: @Context HttpServletRequest request raimund@460: ) { raimund@460: MultivaluedMap params = info.getQueryParameters(); raimund@460: if (params.isEmpty() || !params.containsKey("probeId")) { raimund@460: return defaultRepo.getAll(LMessung.class, "land"); raimund@460: } raimund@460: String probeId = params.getFirst("probeId"); raimund@460: QueryBuilder builder = raimund@460: new QueryBuilder( raimund@460: defaultRepo.entityManager("land"), raimund@460: LMessung.class); raimund@460: builder.and("probeId", probeId); raimund@582: return authorization.filter( raimund@582: request, raimund@582: defaultRepo.filter(builder.getQuery(), "land"), raimund@582: LMessung.class); raimund@460: } raimund@460: raimund@460: /** raimund@627: * Get a Messung object by id. raimund@627: *

raimund@627: * The id is appended to the URL as a path parameter. raimund@627: *

raimund@627: * Example: http://example.com/messung/{id} raimund@460: * raimund@627: * @return Response object containing a single Messung. raimund@460: */ raimund@460: @GET raimund@460: @Path("/{id}") raimund@460: @Produces(MediaType.APPLICATION_JSON) raimund@460: public Response getById( raimund@460: @Context HttpHeaders headers, raimund@582: @Context HttpServletRequest request, raimund@460: @PathParam("id") String id raimund@460: ) { raimund@678: Response response = raimund@678: defaultRepo.getById(LMessung.class, Integer.valueOf(id), "land"); raimund@678: LMessung messung = (LMessung)response.getData(); raimund@678: Violation violation = validator.validate(messung); raimund@678: if (violation.hasErrors() || violation.hasWarnings()) { raimund@678: response.setErrors(violation.getErrors()); raimund@678: response.setWarnings(violation.getWarnings()); raimund@678: } raimund@582: return authorization.filter( raimund@582: request, raimund@678: response, raimund@582: LMessung.class); raimund@460: } raimund@460: raimund@627: /** raimund@627: * Create a Messung object. raimund@627: *

raimund@627: * The new object is embedded in the post data as JSON formatted string. raimund@627: *

raimund@627: *

raimund@627:      * 
raimund@627:      * {
raimund@627:      *  "owner": [boolean],
raimund@627:      *  "probeId": [number],
raimund@627:      *  "mmtId": [string],
raimund@627:      *  "nebenprobenNr": [string],
raimund@627:      *  "messdauer": [number],
raimund@627:      *  "fertig": [boolean],
raimund@627:      *  "geplant": [boolean],
raimund@627:      *  "messungsIdAlt": [string],
raimund@627:      *  "treeModified": null,
raimund@627:      *  "parentModified": null,
raimund@627:      *  "messzeitpunkt": [date],
raimund@627:      *  "letzteAenderung": [date]
raimund@627:      * }
raimund@627:      * 
raimund@627:      * 
raimund@627: * raimund@627: * @return A response object containing the created Messung. raimund@627: */ raimund@460: @POST raimund@460: @Path("/") raimund@460: @Produces(MediaType.APPLICATION_JSON) raimund@460: public Response create( raimund@460: @Context HttpHeaders headers, raimund@582: @Context HttpServletRequest request, raimund@460: LMessung messung raimund@460: ) { raimund@582: if (!authorization.isAuthorized( raimund@582: request, raimund@582: messung, raimund@582: RequestMethod.POST, raimund@582: LMessung.class) raimund@582: ) { raimund@460: return new Response(false, 699, null); raimund@460: } raimund@582: raimund@678: Violation violation = validator.validate(messung); raimund@678: if (violation.hasErrors()) { raimund@678: Response response = new Response(false, 604, messung); raimund@678: response.setErrors(violation.getErrors()); raimund@678: response.setWarnings(violation.getWarnings()); raimund@678: return response; raimund@678: } raimund@678: raimund@460: /* Persist the new messung object*/ raimund@460: Response response = defaultRepo.create(messung, "land"); raimund@460: LMessung ret = (LMessung)response.getData(); raimund@460: /* Create and persist a new probe translation object*/ raimund@460: MessungTranslation trans = new MessungTranslation(); raimund@460: trans.setMessungsId(ret); raimund@460: defaultRepo.create(trans, "land"); raimund@460: /* Get and return the new probe object*/ raimund@460: Response created = raimund@460: defaultRepo.getById(LMessung.class, ret.getId(), "land"); raimund@678: if(violation.hasWarnings()) { raimund@678: created.setWarnings(violation.getWarnings()); raimund@678: } raimund@678: raimund@601: return authorization.filter( raimund@601: request, raimund@678: created, raimund@601: LMessung.class); raimund@460: } raimund@460: raimund@460: /** rrenkert@628: * Update an existing Messung object. raimund@627: *

raimund@627: * The object to update should come as JSON formatted string. raimund@627: *

raimund@627:      * 
raimund@627:      * {
raimund@627:      *  "id": [number],
raimund@627:      *  "owner": [boolean],
raimund@627:      *  "probeId": [number],
raimund@627:      *  "mmtId": [string],
raimund@627:      *  "nebenprobenNr": [string],
raimund@627:      *  "messdauer": [number],
raimund@627:      *  "fertig": [boolean],
raimund@627:      *  "geplant": [boolean],
raimund@627:      *  "messungsIdAlt": [number],
raimund@627:      *  "treeModified": [timestamp],
raimund@627:      *  "parentModified": [timestamp],
raimund@627:      *  "messzeitpunkt": [date],
raimund@627:      *  "letzteAenderung": [date]
raimund@627:      * }
raimund@627:      * 
raimund@627:      * 
raimund@460: * raimund@627: * @return Response object containing the updated Messung object. raimund@460: */ raimund@460: @PUT raimund@557: @Path("/{id}") raimund@460: @Produces(MediaType.APPLICATION_JSON) raimund@582: public Response update( raimund@582: @Context HttpHeaders headers, raimund@582: @Context HttpServletRequest request, raimund@582: LMessung messung raimund@582: ) { raimund@582: if (!authorization.isAuthorized( raimund@582: request, raimund@582: messung, raimund@582: RequestMethod.PUT, raimund@582: LMessung.class) raimund@582: ) { raimund@460: return new Response(false, 699, null); raimund@460: } raimund@595: if (lock.isLocked(messung)) { raimund@595: return new Response(false, 697, null); raimund@595: } raimund@678: Violation violation = validator.validate(messung); raimund@678: if (violation.hasErrors()) { raimund@678: Response response = new Response(false, 604, messung); raimund@678: response.setErrors(violation.getErrors()); raimund@678: response.setWarnings(violation.getWarnings()); raimund@678: return response; raimund@678: } raimund@596: messung.setLetzteAenderung(new Timestamp(new Date().getTime())); raimund@460: Response response = defaultRepo.update(messung, "land"); raimund@460: Response updated = defaultRepo.getById( raimund@460: LMessung.class, raimund@460: ((LMessung)response.getData()).getId(), "land"); raimund@678: if(violation.hasWarnings()) { raimund@678: updated.setWarnings(violation.getWarnings()); raimund@678: } raimund@601: return authorization.filter( raimund@601: request, raimund@601: updated, raimund@601: LMessung.class); raimund@460: } raimund@460: raimund@460: /** raimund@627: * Delete an existing Messung object by id. raimund@627: *

raimund@627: * The id is appended to the URL as a path parameter. raimund@627: *

raimund@627: * Example: http://example.com/messung/{id} raimund@460: * raimund@460: * @return Response object. raimund@460: */ raimund@460: @DELETE raimund@460: @Path("/{id}") raimund@460: @Produces(MediaType.APPLICATION_JSON) raimund@460: public Response delete( raimund@460: @Context HttpHeaders headers, raimund@582: @Context HttpServletRequest request, raimund@460: @PathParam("id") String id raimund@460: ) { raimund@460: /* Get the messung object by id*/ raimund@460: Response messung = raimund@460: defaultRepo.getById(LMessung.class, Integer.valueOf(id), "land"); raimund@460: LMessung messungObj = (LMessung)messung.getData(); raimund@582: if (!authorization.isAuthorized( raimund@582: request, raimund@602: messungObj, raimund@582: RequestMethod.DELETE, raimund@582: LMessung.class) raimund@582: ) { raimund@582: return new Response(false, 699, null); raimund@582: } raimund@595: if (lock.isLocked(messung)) { raimund@595: return new Response(false, 697, null); raimund@595: } raimund@681: raimund@681: QueryBuilder mwBuilder = raimund@681: new QueryBuilder( raimund@681: defaultRepo.entityManager("land"), LMesswert.class); raimund@681: mwBuilder.and("messungsId", messungObj.getId()); raimund@681: QueryBuilder mkBuilder = raimund@681: new QueryBuilder( raimund@681: defaultRepo.entityManager("land"), LKommentarM.class); raimund@681: mkBuilder.and("messungsId", messungObj.getId()); raimund@681: QueryBuilder msBuilder = raimund@681: new QueryBuilder( raimund@681: defaultRepo.entityManager("land"), LStatus.class); raimund@681: msBuilder.and("messungsId", messungObj.getId()); raimund@681: raimund@681: List messwerte = raimund@681: (List)defaultRepo.filter(mwBuilder.getQuery(), "land").getData(); raimund@681: List kommentare = raimund@681: (List)defaultRepo.filter(mkBuilder.getQuery(), "land").getData(); raimund@681: List status = raimund@681: (List)defaultRepo.filter(msBuilder.getQuery(), "land").getData(); raimund@681: raimund@681: if (!messwerte.isEmpty() || raimund@681: !kommentare.isEmpty() || raimund@681: !status.isEmpty() raimund@681: ) { raimund@681: return new Response(false, 696, messung); raimund@681: } raimund@681: raimund@460: /* Create a query and request the messungTranslation object for the raimund@460: * messung*/ raimund@460: QueryBuilder builder = raimund@460: new QueryBuilder( raimund@460: defaultRepo.entityManager("land"), MessungTranslation.class); raimund@460: builder.and("messungs", messungObj.getId()); raimund@460: Response messungTrans = defaultRepo.filter(builder.getQuery(), "land"); raimund@460: @SuppressWarnings("unchecked") raimund@460: MessungTranslation messungTransObj = ((List)messungTrans.getData()).get(0); raimund@460: /* Delete the messung translation object*/ raimund@460: defaultRepo.delete(messungTransObj, "land"); raimund@460: /* Delete the probe object*/ raimund@460: Response response = defaultRepo.delete(messungObj, "land"); raimund@460: return response; raimund@460: } raimund@460: }