source: DASISH/t5.6/backend/annotator-backend/trunk/annotator-backend/src/main/java/eu/dasish/annotation/backend/rest/AnnotationResource.java @ 4207

Last change on this file since 4207 was 4207, checked in by olhsha, 10 years ago

adding trasnactional, refactoring and fixing bugs in updated annotations, removing try-catch from resource methods (The Greek's advice)

File size: 19.3 KB
RevLine 
[3154]1/*
2 * Copyright (C) 2013 DASISH
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 */
18package eu.dasish.annotation.backend.rest;
19
[3168]20import eu.dasish.annotation.backend.BackendConstants;
[3477]21import eu.dasish.annotation.backend.dao.DBIntegrityService;
[3154]22import eu.dasish.annotation.schema.Annotation;
[3609]23import eu.dasish.annotation.schema.AnnotationActionName;
24import eu.dasish.annotation.schema.AnnotationInfoList;
[3909]25import eu.dasish.annotation.schema.Action;
26import eu.dasish.annotation.schema.ActionList;
[4028]27import eu.dasish.annotation.schema.AnnotationBody;
[3154]28import eu.dasish.annotation.schema.ObjectFactory;
[3637]29import eu.dasish.annotation.schema.Permission;
[3909]30import eu.dasish.annotation.schema.PermissionActionName;
[3781]31import eu.dasish.annotation.schema.UserWithPermissionList;
32import eu.dasish.annotation.schema.ReferenceList;
[3609]33import eu.dasish.annotation.schema.ResponseBody;
[3972]34import java.io.IOException;
[4173]35import java.net.URI;
[3609]36import java.sql.Timestamp;
[3909]37import java.util.ArrayList;
[3609]38import java.util.List;
[3455]39import java.util.UUID;
[3206]40import javax.servlet.http.HttpServletRequest;
[3972]41import javax.servlet.http.HttpServletResponse;
[3180]42import javax.ws.rs.Consumes;
[3168]43import javax.ws.rs.DELETE;
[3154]44import javax.ws.rs.GET;
[3180]45import javax.ws.rs.POST;
[3609]46import javax.ws.rs.PUT;
[3154]47import javax.ws.rs.Path;
48import javax.ws.rs.PathParam;
49import javax.ws.rs.Produces;
[3609]50import javax.ws.rs.QueryParam;
[3206]51import javax.ws.rs.core.Context;
[3154]52import javax.ws.rs.core.MediaType;
[3639]53import javax.ws.rs.core.UriInfo;
[3722]54import javax.ws.rs.ext.Providers;
[3154]55import javax.xml.bind.JAXBElement;
[3452]56import org.springframework.beans.factory.annotation.Autowired;
[3949]57import org.springframework.security.access.annotation.Secured;
[3154]58import org.springframework.stereotype.Component;
[4010]59import org.slf4j.Logger;
60import org.slf4j.LoggerFactory;
[4207]61import org.springframework.transaction.annotation.Transactional;
[3154]62
63/**
64 *
65 * @author olhsha
66 */
67@Component
68@Path("/annotations")
[4207]69@Transactional(rollbackFor = {Exception.class})
[3154]70public class AnnotationResource {
[3609]71
[3452]72    @Autowired
[3477]73    private DBIntegrityService dbIntegrityService;
[3206]74    @Context
75    private HttpServletRequest httpServletRequest;
[3639]76    @Context
[3972]77    private HttpServletResponse httpServletResponse;
78    @Context
[3639]79    private UriInfo uriInfo;
[3722]80    @Context
[4000]81    private Providers providers;
[4173]82   
83   
[3972]84    final String default_permission = "reader";
[4010]85    private static final Logger logger = LoggerFactory.getLogger(AnnotationResource.class);
86
87    public void setUriInfo(UriInfo uriInfo) {
88        this.uriInfo = uriInfo;
[4000]89    }
[4010]90
91    public void setHttpServletResponse(HttpServletResponse httpServletResponse) {
92        this.httpServletResponse = httpServletResponse;
[4000]93    }
[3841]94
[4010]95    public void setHttpServletRequest(HttpServletRequest httpServletRequest) {
96        this.httpServletRequest = httpServletRequest;
97    }
98
[4173]99 
100   
[4010]101    public void setProviders(Providers providers) {
102        this.providers = providers;
103    }
104
[3218]105    public AnnotationResource() {
[3206]106    }
[3218]107
[3154]108    @GET
109    @Produces(MediaType.TEXT_XML)
[3218]110    @Path("{annotationid: " + BackendConstants.regExpIdentifier + "}")
[3949]111    @Secured("ROLE_USER")
[4207]112    @Transactional(readOnly = true)
113    public JAXBElement<Annotation> getAnnotation(@PathParam("annotationid") String ExternalIdentifier) throws IOException {
[4173]114        URI baseURI = uriInfo.getBaseUri();
115        String baseURIstr = baseURI.toString();
116        dbIntegrityService.setServiceURI(baseURIstr);
[3477]117        final Number annotationID = dbIntegrityService.getAnnotationInternalIdentifier(UUID.fromString(ExternalIdentifier));
[4173]118        String remoteUser = httpServletRequest.getRemoteUser();
119        final Number userID = dbIntegrityService.getUserInternalIDFromRemoteID(remoteUser);
[3972]120        if (canRead(userID, annotationID)) {
121            final Annotation annotation = dbIntegrityService.getAnnotation(annotationID);
122            JAXBElement<Annotation> rootElement = new ObjectFactory().createAnnotation(annotation);
[4010]123            logger.info("getAnnotation method: OK");
[3972]124            return rootElement;
125        } else {
[4207]126            httpServletResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
[3972]127            return null;
128        }
[3841]129
[3154]130    }
[3218]131
[3841]132    //TODO: unit test
[3609]133    @GET
134    @Produces(MediaType.TEXT_XML)
[3784]135    @Path("{annotationid: " + BackendConstants.regExpIdentifier + "}/targets")
[3949]136    @Secured("ROLE_USER")
[4207]137    @Transactional(readOnly = true)
138    public JAXBElement<ReferenceList> getAnnotationTargets(@PathParam("annotationid") String ExternalIdentifier) throws IOException {
[3647]139        dbIntegrityService.setServiceURI(uriInfo.getBaseUri().toString());
[3609]140        final Number annotationID = dbIntegrityService.getAnnotationInternalIdentifier(UUID.fromString(ExternalIdentifier));
[3972]141        final Number userID = dbIntegrityService.getUserInternalIDFromRemoteID(httpServletRequest.getRemoteUser());
142        if (canRead(userID, annotationID)) {
143            final ReferenceList TargetList = dbIntegrityService.getAnnotationTargets(annotationID);
[4010]144            logger.info("getAnnotationTargets method: OK");
[3972]145            return new ObjectFactory().createTargetList(TargetList);
146        } else {
[4207]147            httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
[3972]148            return null;
149        }
[3609]150    }
[3841]151
[3609]152    // TODO Unit test
153    @GET
154    @Produces(MediaType.TEXT_XML)
155    @Path("")
[3949]156    @Secured("ROLE_USER")
[4207]157    @Transactional(readOnly = true)
[3609]158    public JAXBElement<AnnotationInfoList> getFilteredAnnotations(@QueryParam("link") String link,
[3841]159            @QueryParam("text") String text,
160            @QueryParam("access") String permission,
[3972]161            @QueryParam("namespace") String namespace,
162            @QueryParam("owner") String ownerExternalId,
[3841]163            @QueryParam("after") Timestamp after,
[4010]164            @QueryParam("before") Timestamp before) {
[3972]165
[3647]166        dbIntegrityService.setServiceURI(uriInfo.getBaseUri().toString());
[3972]167        Number userID = dbIntegrityService.getUserInternalIDFromRemoteID(httpServletRequest.getRemoteUser());
168        UUID ownerExternalUUID = (ownerExternalId != null) ? UUID.fromString(ownerExternalId) : null;
169        String access = (permission != null) ? permission : default_permission;
[4207]170        final AnnotationInfoList annotationInfoList = dbIntegrityService.getFilteredAnnotationInfos(link, text, userID, makeAccessModeChain(access), namespace, ownerExternalUUID, after, before);
[4010]171        logger.info("getFilteredAnnotations method: OK");
[3609]172        return new ObjectFactory().createAnnotationInfoList(annotationInfoList);
173    }
[3841]174
[3609]175    // TODO Unit test   
176    @GET
177    @Produces(MediaType.TEXT_XML)
[3633]178    @Path("{annotationid: " + BackendConstants.regExpIdentifier + "}/permissions")
[3949]179    @Secured("ROLE_USER")
[4207]180    @Transactional(readOnly = true)
181    public JAXBElement<UserWithPermissionList> getAnnotationPermissions(@PathParam("annotationid") String ExternalIdentifier) throws IOException {
[3647]182        dbIntegrityService.setServiceURI(uriInfo.getBaseUri().toString());
[3972]183        final Number annotationID = dbIntegrityService.getAnnotationInternalIdentifier(UUID.fromString(ExternalIdentifier));
184        final Number userID = dbIntegrityService.getUserInternalIDFromRemoteID(httpServletRequest.getRemoteUser());
185        if (canRead(userID, annotationID)) {
186            final UserWithPermissionList permissionList = dbIntegrityService.getPermissionsForAnnotation(annotationID);
[4010]187            logger.info("getAnnotationPermissions method: OK");
[3972]188            return new ObjectFactory().createPermissionList(permissionList);
189        } else {
[4207]190            httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
[3972]191            return null;
192        }
[3841]193
[3609]194    }
195
[3407]196    ///////////////////////////////////////////////////////
[3609]197    // TODO: how to return the status code?
[3168]198    @DELETE
[3218]199    @Path("{annotationid: " + BackendConstants.regExpIdentifier + "}")
[3949]200    @Secured("ROLE_USER")
[4207]201    public String deleteAnnotation(@PathParam("annotationid") String externalIdentifier) throws IOException {
[3647]202        dbIntegrityService.setServiceURI(uriInfo.getBaseUri().toString());
[3477]203        final Number annotationID = dbIntegrityService.getAnnotationInternalIdentifier(UUID.fromString(externalIdentifier));
[3972]204        final Number userID = dbIntegrityService.getUserInternalIDFromRemoteID(httpServletRequest.getRemoteUser());
[4010]205        if (isOwner(userID, annotationID)) {
[3972]206            int[] resultDelete = dbIntegrityService.deleteAnnotation(annotationID);
207            String result = Integer.toString(resultDelete[0]);
[4010]208            logger.info("deleteAnnotation method: OK");
[3972]209            return result + " annotation(s) deleted.";
210        } else {
[4207]211            httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
[4010]212            return null;
[3972]213        }
214
[3168]215    }
[3218]216
[3407]217    ///////////////////////////////////////////////////////
[3218]218    @POST
[3180]219    @Consumes(MediaType.APPLICATION_XML)
220    @Produces(MediaType.APPLICATION_XML)
221    @Path("")
[3949]222    @Secured("ROLE_USER")
[4207]223    public JAXBElement<ResponseBody> createAnnotation(Annotation annotation) throws IOException {
[3647]224        dbIntegrityService.setServiceURI(uriInfo.getBaseUri().toString());
[3972]225        final Number userID = dbIntegrityService.getUserInternalIDFromRemoteID(httpServletRequest.getRemoteUser());
[3909]226        Number annotationID = dbIntegrityService.addUsersAnnotation(userID, annotation);
[4010]227        logger.info("createAnnotation method: OK");
[3909]228        return new ObjectFactory().createResponseBody(makeAnnotationResponseEnvelope(annotationID));
[3609]229    }
[3841]230
[3609]231    ///////////////////////////////////////////////////////
232    // TODO: unit test
233    @PUT
234    @Consumes(MediaType.APPLICATION_XML)
235    @Produces(MediaType.APPLICATION_XML)
236    @Path("{annotationid: " + BackendConstants.regExpIdentifier + "}")
[3949]237    @Secured("ROLE_USER")
[4207]238    public JAXBElement<ResponseBody> updateAnnotation(@PathParam("annotationid") String externalIdentifier, Annotation annotation) throws IOException {
[3647]239        String path = uriInfo.getBaseUri().toString();
[3639]240        dbIntegrityService.setServiceURI(path);
[3911]241        String annotationURI = annotation.getURI();
242        if (!(path + "annotations/" + externalIdentifier).equals(annotationURI)) {
[4010]243            logger.error("Wrong request: the external annotation ID and the annotation ID from the request body do not match.");
244            logger.error("Will do nothing.");
245            return null;
[3609]246        }
[3972]247        final Number annotationID = dbIntegrityService.getAnnotationInternalIdentifier(UUID.fromString(externalIdentifier));
248        final Number userID = dbIntegrityService.getUserInternalIDFromRemoteID(httpServletRequest.getRemoteUser());
249        if (canWrite(userID, annotationID)) {
250            int updatedRows = dbIntegrityService.updateUsersAnnotation(userID, annotation);
[4010]251            logger.info("updateAnnotation method: OK");
[3972]252            return new ObjectFactory().createResponseBody(makeAnnotationResponseEnvelope(annotationID));
[4010]253
[3972]254        } else {
[4207]255            httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
[3972]256            return null;
257        }
[3909]258
[3609]259    }
[4207]260
[4028]261    @PUT
262    @Consumes(MediaType.APPLICATION_XML)
263    @Produces(MediaType.APPLICATION_XML)
264    @Path("{annotationid: " + BackendConstants.regExpIdentifier + "}/body")
265    @Secured("ROLE_USER")
[4207]266    public JAXBElement<ResponseBody> updateAnnotationBody(@PathParam("annotationid") String externalIdentifier, AnnotationBody annotationBody) throws IOException {
[4028]267        String path = uriInfo.getBaseUri().toString();
268        dbIntegrityService.setServiceURI(path);
[4207]269
[4028]270        final Number annotationID = dbIntegrityService.getAnnotationInternalIdentifier(UUID.fromString(externalIdentifier));
271        final Number userID = dbIntegrityService.getUserInternalIDFromRemoteID(httpServletRequest.getRemoteUser());
272        if (canWrite(userID, annotationID)) {
273            int updatedRows = dbIntegrityService.updateAnnotationBody(annotationID, annotationBody);
274            logger.info("updateAnnotationBody method: OK");
275            return new ObjectFactory().createResponseBody(makeAnnotationResponseEnvelope(annotationID));
276        } else {
[4207]277            httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
[4028]278            return null;
279        }
280
281    }
282
[3637]283    @PUT
[3972]284    @Consumes(MediaType.APPLICATION_XML)
[3910]285    @Produces(MediaType.APPLICATION_XML)
[3637]286    @Path("{annotationid: " + BackendConstants.regExpIdentifier + "}/permissions/{userid: " + BackendConstants.regExpIdentifier + "}")
[3949]287    @Secured("ROLE_USER")
[4207]288    public String updatePermission(@PathParam("annotationid") String annotationExternalId, @PathParam("userid") String userExternalId, Permission permission) throws IOException {
[3647]289        dbIntegrityService.setServiceURI(uriInfo.getBaseUri().toString());
[3637]290        final Number annotationID = dbIntegrityService.getAnnotationInternalIdentifier(UUID.fromString(annotationExternalId));
[3972]291        final Number remoteUserID = dbIntegrityService.getUserInternalIDFromRemoteID(httpServletRequest.getRemoteUser());
[3637]292        final Number userID = dbIntegrityService.getUserInternalIdentifier(UUID.fromString(userExternalId));
[3972]293        if (isOwner(remoteUserID, annotationID)) {
294            int result = (dbIntegrityService.getPermission(annotationID, userID) != null)
295                    ? dbIntegrityService.updateAnnotationPrincipalPermission(annotationID, userID, permission)
296                    : dbIntegrityService.addAnnotationPrincipalPermission(annotationID, userID, permission);
[4010]297            logger.info("updatePermission method: OK");
[3972]298            return result + " rows are updated/added";
299
[3841]300        } else {
[4207]301            httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
[3972]302            return null;
[3637]303        }
304    }
[3841]305
[3637]306    @PUT
307    @Consumes(MediaType.APPLICATION_XML)
[3909]308    @Produces(MediaType.APPLICATION_XML)
[3637]309    @Path("{annotationid: " + BackendConstants.regExpIdentifier + "}/permissions/")
[3949]310    @Secured("ROLE_USER")
[4207]311    public JAXBElement<ResponseBody> updatePermissions(@PathParam("annotationid") String annotationExternalId, UserWithPermissionList permissions) throws IOException {
[3647]312        dbIntegrityService.setServiceURI(uriInfo.getBaseUri().toString());
[3637]313        final Number annotationID = dbIntegrityService.getAnnotationInternalIdentifier(UUID.fromString(annotationExternalId));
[3972]314        final Number remoteUserID = dbIntegrityService.getUserInternalIDFromRemoteID(httpServletRequest.getRemoteUser());
315        if (isOwner(remoteUserID, annotationID)) {
316            int updatedRows = dbIntegrityService.updatePermissions(annotationID, permissions);
[4010]317            logger.info("updatePermissions method: OK");
[3972]318            return new ObjectFactory().createResponseBody(makePermissionResponseEnvelope(annotationID));
319        } else {
[4207]320            httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
[3972]321            return null;
322        }
[3637]323    }
[3841]324
[3909]325    /////////////////////////////////////////
[4010]326    private ResponseBody makeAnnotationResponseEnvelope(Number annotationID) {
[3609]327        ResponseBody result = new ResponseBody();
[3972]328        result.setPermissions(null);
[3909]329        Annotation annotation = dbIntegrityService.getAnnotation(annotationID);
330        result.setAnnotation(annotation);
331        List<String> targetsNoCached = dbIntegrityService.getTargetsWithNoCachedRepresentation(annotationID);
332        ActionList actionList = new ActionList();
333        result.setActionList(actionList);
[3972]334        actionList.getAction().addAll(makeActionList(targetsNoCached, AnnotationActionName.CREATE_CACHED_REPRESENTATION.value()));
[3609]335        return result;
336    }
[3841]337
[3909]338    /////////////////////////////////////////
[4010]339    private ResponseBody makePermissionResponseEnvelope(Number annotationID) {
[3909]340        ResponseBody result = new ResponseBody();
[3972]341        result.setAnnotation(null);
[3909]342        UserWithPermissionList permissions = dbIntegrityService.getPermissionsForAnnotation(annotationID);
343        result.setPermissions(permissions);
344        List<String> usersWithNoInfo = dbIntegrityService.getUsersWithNoInfo(annotationID);
345        ActionList actionList = new ActionList();
346        result.setActionList(actionList);
347        actionList.getAction().addAll(makeActionList(usersWithNoInfo, PermissionActionName.PROVIDE_USER_INFO.value()));
348        return result;
[3180]349    }
[3972]350
[4207]351    // REFACTOR : move to the integrity service all te methods below 
[3972]352    private List<Action> makeActionList(List<String> resourceURIs, String message) {
353        if (resourceURIs != null) {
354            if (resourceURIs.isEmpty()) {
[3909]355                return (new ArrayList<Action>());
356            } else {
[3972]357                List<Action> result = new ArrayList<Action>();
[3909]358                for (String resourceURI : resourceURIs) {
359                    Action action = new Action();
360                    result.add(action);
361                    action.setMessage(message);
362                    action.setObject(resourceURI);
363                }
364                return result;
[3972]365            }
366        } else {
[3909]367            return null;
368        }
[3906]369    }
[3972]370
371    private boolean canRead(Number userID, Number annotationID) {
372        final Permission permission = dbIntegrityService.getPermission(annotationID, userID);
373        if (permission != null) {
374            return (permission.value() == Permission.OWNER.value() || permission.value() == Permission.WRITER.value() || permission.value() == Permission.READER.value());
375        } else {
376            return false;
377        }
378    }
379
380    private boolean canWrite(Number userID, Number annotationID) {
381        final Permission permission = dbIntegrityService.getPermission(annotationID, userID);
382        if (permission != null) {
383            return (permission.value() == Permission.OWNER.value() || permission.value() == Permission.WRITER.value());
384        } else {
385            return false;
386        }
387    }
388
389    private boolean isOwner(Number userID, Number annotationID) {
390        final Permission permission = dbIntegrityService.getPermission(annotationID, userID);
391        if (permission != null) {
392            return (permission.value() == Permission.OWNER.value());
393        } else {
394            return false;
395        }
396    }
[4207]397
398    private String[] makeAccessModeChain(String accessMode) {
399        if (accessMode != null) {
400            if (accessMode == Permission.OWNER.value()) {
401                String[] result = new String[1];
402                result[0] = accessMode;
403                return result;
404            } else {
405                if (accessMode == Permission.WRITER.value()) {
406                    String[] result = new String[2];
407                    result[0] = Permission.WRITER.value();
408                    result[1] = Permission.OWNER.value();
409                    return result;
410                } else {
411                    if (accessMode == Permission.READER.value()) {
412                        String[] result = new String[3];
413                        result[0] = Permission.READER.value();
414                        result[1] = Permission.WRITER.value();
415                        result[2] = Permission.OWNER.value();
416                        return result;
417                    } else {
418                        logger.error("Invalide access " + accessMode);
419                        return null;
420                    }
421
422                }
423            }
424
425        } else {
426            return null;
427        }
428    }
[3154]429}
Note: See TracBrowser for help on using the repository browser.