001/*
002 * (C) Copyright 2018-2020 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 *       Kevin Leturc <kleturc@nuxeo.com>
018 *       Nuno Cunha <ncunha@nuxeo.com>
019 */
020package org.nuxeo.ecm.platform.comment.impl;
021
022import static org.nuxeo.ecm.core.io.registry.reflect.Instantiations.SINGLETON;
023import static org.nuxeo.ecm.core.io.registry.reflect.Priorities.REFERENCE;
024import static org.nuxeo.ecm.platform.comment.api.CommentConstants.COMMENT_ANCESTOR_IDS_FIELD;
025import static org.nuxeo.ecm.platform.comment.api.CommentConstants.COMMENT_AUTHOR_FIELD;
026import static org.nuxeo.ecm.platform.comment.api.CommentConstants.COMMENT_CREATION_DATE_FIELD;
027import static org.nuxeo.ecm.platform.comment.api.CommentConstants.COMMENT_ENTITY_TYPE;
028import static org.nuxeo.ecm.platform.comment.api.CommentConstants.COMMENT_ID_FIELD;
029import static org.nuxeo.ecm.platform.comment.api.CommentConstants.COMMENT_LAST_REPLY_DATE_FIELD;
030import static org.nuxeo.ecm.platform.comment.api.CommentConstants.COMMENT_MODIFICATION_DATE_FIELD;
031import static org.nuxeo.ecm.platform.comment.api.CommentConstants.COMMENT_NUMBER_OF_REPLIES_FIELD;
032import static org.nuxeo.ecm.platform.comment.api.CommentConstants.COMMENT_PARENT_ID_FIELD;
033import static org.nuxeo.ecm.platform.comment.api.CommentConstants.COMMENT_PERMISSIONS_FIELD;
034import static org.nuxeo.ecm.platform.comment.api.CommentConstants.COMMENT_TEXT_FIELD;
035import static org.nuxeo.ecm.platform.comment.api.ExternalEntityConstants.EXTERNAL_ENTITY;
036import static org.nuxeo.ecm.platform.comment.api.ExternalEntityConstants.EXTERNAL_ENTITY_ID_FIELD;
037import static org.nuxeo.ecm.platform.comment.api.ExternalEntityConstants.EXTERNAL_ENTITY_ORIGIN_FIELD;
038
039import java.io.IOException;
040import java.util.Arrays;
041import java.util.Collection;
042import java.util.Collections;
043
044import javax.inject.Inject;
045
046import org.nuxeo.ecm.core.api.CoreInstance;
047import org.nuxeo.ecm.core.api.CoreSession;
048import org.nuxeo.ecm.core.api.DocumentRef;
049import org.nuxeo.ecm.core.api.IdRef;
050import org.nuxeo.ecm.core.api.NuxeoPrincipal;
051import org.nuxeo.ecm.core.api.PartialList;
052import org.nuxeo.ecm.core.api.security.PermissionProvider;
053import org.nuxeo.ecm.core.io.marshallers.json.ExtensibleEntityJsonWriter;
054import org.nuxeo.ecm.core.io.registry.reflect.Setup;
055import org.nuxeo.ecm.platform.comment.api.Comment;
056import org.nuxeo.ecm.platform.comment.api.CommentManager;
057import org.nuxeo.ecm.platform.comment.api.ExternalEntity;
058import org.nuxeo.runtime.api.Framework;
059
060import com.fasterxml.jackson.core.JsonGenerator;
061
062/**
063 * @since 10.3
064 */
065@Setup(mode = SINGLETON, priority = REFERENCE)
066public class CommentJsonWriter extends ExtensibleEntityJsonWriter<Comment> {
067
068    public static final String FETCH_REPLIES_SUMMARY = "repliesSummary";
069
070    @Inject
071    protected CommentManager commentManager;
072
073    public CommentJsonWriter() {
074        super(COMMENT_ENTITY_TYPE, Comment.class);
075    }
076
077    @Override
078    protected void writeEntityBody(Comment entity, JsonGenerator jg) throws IOException {
079        writeCommentEntity(entity, jg);
080        CoreSession session = ctx.getSession(null).getSession();
081        NuxeoPrincipal principal = session.getPrincipal();
082        PermissionProvider permissionProvider = Framework.getService(PermissionProvider.class);
083
084        // Write permissions of current user on the annotation,
085        // which are the ones granted on the commented document
086        Collection<String> permissions = CoreInstance.doPrivileged(session, s -> {
087            if (entity.getId() == null) {
088                return Collections.emptyList();
089            }
090            DocumentRef ancestorRef = Framework.getService(CommentManager.class)
091                                               .getTopLevelDocumentRef(s, new IdRef(entity.getId()));
092            return s.filterGrantedPermissions(principal, ancestorRef,
093                    Arrays.asList(permissionProvider.getPermissions()));
094        });
095        jg.writeArrayFieldStart(COMMENT_PERMISSIONS_FIELD);
096        for (String permission : permissions) {
097            jg.writeString(permission);
098        }
099        jg.writeEndArray();
100        boolean includeRepliesSummary = ctx.getFetched(COMMENT_ENTITY_TYPE).contains(FETCH_REPLIES_SUMMARY);
101        if (includeRepliesSummary) {
102            writeRepliesSummary(session, entity, jg);
103        }
104    }
105
106    protected static void writeCommentEntity(Comment entity, JsonGenerator jg) throws IOException {
107        jg.writeStringField(COMMENT_ID_FIELD, entity.getId());
108        jg.writeStringField(COMMENT_PARENT_ID_FIELD, entity.getParentId());
109        jg.writeArrayFieldStart(COMMENT_ANCESTOR_IDS_FIELD);
110        for (String ancestorId : entity.getAncestorIds()) {
111            jg.writeString(ancestorId);
112        }
113        jg.writeEndArray();
114        jg.writeStringField(COMMENT_AUTHOR_FIELD, entity.getAuthor());
115        jg.writeStringField(COMMENT_TEXT_FIELD, entity.getText());
116
117        String creationDate = entity.getCreationDate() != null ? entity.getCreationDate().toString() : null;
118        jg.writeStringField(COMMENT_CREATION_DATE_FIELD, creationDate);
119        String modificationDate = entity.getModificationDate() != null ? entity.getModificationDate().toString() : null;
120        jg.writeStringField(COMMENT_MODIFICATION_DATE_FIELD, modificationDate);
121
122        if (entity instanceof ExternalEntity) {
123            jg.writeStringField(EXTERNAL_ENTITY_ID_FIELD, ((ExternalEntity) entity).getEntityId());
124            jg.writeStringField(EXTERNAL_ENTITY_ORIGIN_FIELD, ((ExternalEntity) entity).getOrigin());
125            jg.writeStringField(EXTERNAL_ENTITY, ((ExternalEntity) entity).getEntity());
126        }
127    }
128
129    protected void writeRepliesSummary(CoreSession session, Comment entity, JsonGenerator jg) throws IOException {
130        PartialList<Comment> comments = commentManager.getComments(session, entity.getId(), 1L, 0L, false);
131        jg.writeNumberField(COMMENT_NUMBER_OF_REPLIES_FIELD, comments.totalSize());
132        if (!comments.isEmpty()) {
133            jg.writeStringField(COMMENT_LAST_REPLY_DATE_FIELD, comments.get(0).getCreationDate().toString());
134        }
135    }
136}