001/*
002 * (C) Copyright 2018 Nuxeo (http://nuxeo.com/) and others.
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 *
016 * Contributors:
017 *     Funsho David
018 */
019
020package org.nuxeo.ecm.restapi.server.jaxrs.comment;
021
022import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
023
024import java.util.ArrayList;
025import java.util.List;
026
027import javax.ws.rs.DELETE;
028import javax.ws.rs.GET;
029import javax.ws.rs.POST;
030import javax.ws.rs.PUT;
031import javax.ws.rs.Path;
032import javax.ws.rs.PathParam;
033import javax.ws.rs.Produces;
034import javax.ws.rs.QueryParam;
035import javax.ws.rs.core.MediaType;
036import javax.ws.rs.core.Response;
037
038import org.nuxeo.ecm.core.api.CoreSession;
039import org.nuxeo.ecm.core.api.DocumentModel;
040import org.nuxeo.ecm.core.api.NuxeoException;
041import org.nuxeo.ecm.platform.comment.api.Annotation;
042import org.nuxeo.ecm.platform.comment.api.AnnotationService;
043import org.nuxeo.ecm.platform.comment.api.Comment;
044import org.nuxeo.ecm.platform.comment.api.CommentManager;
045import org.nuxeo.ecm.webengine.model.WebAdapter;
046import org.nuxeo.ecm.webengine.model.impl.DefaultAdapter;
047import org.nuxeo.runtime.api.Framework;
048
049import com.fasterxml.jackson.core.JsonProcessingException;
050import com.fasterxml.jackson.databind.JavaType;
051import com.fasterxml.jackson.databind.ObjectMapper;
052
053/**
054 * @since 10.1
055 */
056@WebAdapter(name = AnnotationAdapter.NAME, type = "annotationAdapter")
057@Produces(MediaType.APPLICATION_JSON)
058public class AnnotationAdapter extends DefaultAdapter {
059
060    public static final String NAME = "annotation";
061
062    private static final ObjectMapper MAPPER = new ObjectMapper();
063
064    private static final JavaType LIST_STRING_TYPE = MAPPER.getTypeFactory()
065                                                           .constructCollectionType(List.class, String.class);
066
067    @POST
068    public Response createAnnotation(Annotation annotation) {
069        DocumentModel doc = getTarget().getAdapter(DocumentModel.class);
070        annotation.setParentId(doc.getId());
071        AnnotationService annotationService = Framework.getService(AnnotationService.class);
072        // Set logged user as author
073        annotation.setAuthor(getContext().getCoreSession().getPrincipal().getName());
074        Annotation result = annotationService.createAnnotation(getContext().getCoreSession(), annotation);
075        return Response.status(Response.Status.CREATED).entity(result).build();
076    }
077
078    @GET
079    public List<Annotation> getAnnotations(@QueryParam("xpath") String xpath) {
080        DocumentModel doc = getTarget().getAdapter(DocumentModel.class);
081        AnnotationService annotationService = Framework.getService(AnnotationService.class);
082        return annotationService.getAnnotations(getContext().getCoreSession(), doc.getId(), xpath);
083    }
084
085    /**
086     * @deprecated since 11.3, use {@link #getCommentsFromBody(String)} instead
087     */
088    @GET
089    @Path("comments")
090    @Deprecated(since = "11.3")
091    public List<Comment> getComments(@QueryParam("annotationIds") List<String> annotationIds) {
092        return Framework.getService(CommentManager.class).getComments(getContext().getCoreSession(), annotationIds);
093    }
094
095    @POST
096    @Path("comments")
097    public List<Comment> getCommentsFromBody(String payload) {
098        try {
099            List<String> annotationIds = MAPPER.readValue(payload, LIST_STRING_TYPE);
100            return Framework.getService(CommentManager.class).getComments(getContext().getCoreSession(), annotationIds);
101        } catch (JsonProcessingException e) {
102            throw new NuxeoException("Unable to read payload", SC_BAD_REQUEST);
103        }
104    }
105
106    @GET
107    @Path("{annotationId}")
108    public Annotation getAnnotation(@PathParam("annotationId") String annotationId) {
109        AnnotationService annotationService = Framework.getService(AnnotationService.class);
110        return annotationService.getAnnotation(getContext().getCoreSession(), annotationId);
111    }
112
113    @GET
114    @Path("external/{entityId}")
115    public Annotation getExternalAnnotation(@PathParam("entityId") String entityId) {
116        DocumentModel doc = getTarget().getAdapter(DocumentModel.class);
117        AnnotationService annotationService = Framework.getService(AnnotationService.class);
118        return annotationService.getExternalAnnotation(getContext().getCoreSession(), doc.getId(), entityId);
119    }
120
121    @PUT
122    @Path("{annotationId}")
123    public Annotation updateAnnotation(@PathParam("annotationId") String annotationId, Annotation annotation) {
124        DocumentModel doc = getTarget().getAdapter(DocumentModel.class);
125        annotation.setParentId(doc.getId());
126        AnnotationService annotationService = Framework.getService(AnnotationService.class);
127        // Fetch original annotation author
128        CoreSession session = getContext().getCoreSession();
129        String author = annotationService.getAnnotation(session, annotationId).getAuthor();
130        annotation.setAuthor(author);
131        annotationService.updateAnnotation(session, annotationId, annotation);
132        return annotation;
133    }
134
135    @PUT
136    @Path("external/{entityId}")
137    public Annotation updateExternalAnnotation(@PathParam("entityId") String entityId, Annotation annotation) {
138        DocumentModel doc = getTarget().getAdapter(DocumentModel.class);
139        AnnotationService annotationService = Framework.getService(AnnotationService.class);
140        // Fetch original annotation author
141        CoreSession session = getContext().getCoreSession();
142        String author = annotationService.getExternalAnnotation(session, doc.getId(), entityId).getAuthor();
143        annotation.setAuthor(author);
144        annotationService.updateExternalAnnotation(getContext().getCoreSession(), doc.getId(), entityId, annotation);
145        return annotation;
146    }
147
148    @DELETE
149    @Path("{annotationId}")
150    public Response deleteAnnotation(@PathParam("annotationId") String annotationId) {
151        AnnotationService annotationService = Framework.getService(AnnotationService.class);
152        annotationService.deleteAnnotation(getContext().getCoreSession(), annotationId);
153        return Response.noContent().build();
154    }
155
156    @DELETE
157    @Path("external/{entityId}")
158    public Response deleteExternalAnnotation(@PathParam("entityId") String entityId) {
159        DocumentModel doc = getTarget().getAdapter(DocumentModel.class);
160        AnnotationService annotationService = Framework.getService(AnnotationService.class);
161        annotationService.deleteExternalAnnotation(getContext().getCoreSession(), doc.getId(), entityId);
162        return Response.noContent().build();
163    }
164
165}