001/*
002 * (C) Copyright 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 */
019
020package org.nuxeo.ecm.platform.comment.listener;
021
022import static org.nuxeo.ecm.core.api.event.DocumentEventTypes.DOCUMENT_CHECKEDIN;
023import static org.nuxeo.ecm.platform.comment.api.CommentConstants.COMMENT_ANCESTOR_IDS_PROPERTY;
024import static org.nuxeo.ecm.platform.comment.api.CommentConstants.COMMENT_PARENT_ID_PROPERTY;
025import static org.nuxeo.ecm.platform.comment.impl.AbstractCommentManager.COMMENTS_DIRECTORY;
026
027import java.util.ArrayList;
028import java.util.Arrays;
029
030import org.nuxeo.ecm.core.api.CoreSession;
031import org.nuxeo.ecm.core.api.DocumentModel;
032import org.nuxeo.ecm.core.api.DocumentModelList;
033import org.nuxeo.ecm.core.api.DocumentRef;
034import org.nuxeo.ecm.core.event.Event;
035import org.nuxeo.ecm.core.event.EventBundle;
036import org.nuxeo.ecm.core.event.EventContext;
037import org.nuxeo.ecm.core.event.PostCommitFilteringEventListener;
038
039/**
040 * Listener that updates {@code comment:parentId} and {@code comment:ancestorIds} on version's comments after the
041 * check-in event.
042 *
043 * @since 11.1
044 */
045public class CheckedInCommentListener implements PostCommitFilteringEventListener {
046
047    @Override
048    public boolean acceptEvent(Event event) {
049        return DOCUMENT_CHECKEDIN.equals(event.getName());
050    }
051
052    @Override
053    public void handleEvent(EventBundle events) {
054        for (Event event : events) {
055            if (acceptEvent(event)) {
056                handleEvent(event);
057            }
058        }
059    }
060
061    protected void handleEvent(Event event) {
062        EventContext ctx = event.getContext();
063        CoreSession session = ctx.getCoreSession();
064        DocumentRef versionRef = (DocumentRef) ctx.getProperty("checkedInVersionRef");
065        if (versionRef != null && session.hasChild(versionRef, COMMENTS_DIRECTORY)) {
066            DocumentModel comments = session.getChild(versionRef, COMMENTS_DIRECTORY);
067            updateCommentProperties(session, comments.getId(), versionRef.reference().toString());
068        }
069    }
070
071    protected void updateCommentProperties(CoreSession session, String ecmParentId, String commentParentId,
072            String... parentCommentAncestorIds) {
073        int limit = 100;
074        long offset = 0;
075        long total = 0;
076        do {
077            DocumentModelList docModels = session.query(
078                    String.format("SELECT * FROM Comment where ecm:parentId='%s'", ecmParentId), null, limit, offset,
079                    true);
080            for (DocumentModel docModel : docModels) {
081                // build current ancestor ids
082                var commentAncestorIds = new ArrayList<>(Arrays.asList(parentCommentAncestorIds));
083                commentAncestorIds.add(commentParentId);
084                docModel.setPropertyValue(COMMENT_ANCESTOR_IDS_PROPERTY, commentAncestorIds);
085                docModel.setPropertyValue(COMMENT_PARENT_ID_PROPERTY, commentParentId);
086                session.saveDocument(docModel);
087                // loop on replies
088                updateCommentProperties(session, docModel.getId(), docModel.getId(),
089                        commentAncestorIds.toArray(String[]::new));
090            }
091            offset += limit;
092            if (total == 0) {
093                total = docModels.totalSize();
094            }
095            session.save();
096        } while (offset < total);
097    }
098}