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

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

shibbolized

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