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.platform.comment.impl;
021
022import static java.util.function.Predicate.isEqual;
023import static org.nuxeo.ecm.platform.comment.api.CommentConstants.MIGRATION_STATE_PROPERTY;
024import static org.nuxeo.ecm.platform.comment.api.CommentConstants.MIGRATION_STATE_RELATION;
025import static org.nuxeo.ecm.platform.comment.api.CommentConstants.MIGRATION_STEP_RELATION_TO_PROPERTY;
026import static org.nuxeo.ecm.platform.comment.workflow.utils.CommentsConstants.COMMENT_PARENT_ID;
027import java.util.Collections;
028import java.util.List;
029import java.util.Map;
030
031import org.apache.logging.log4j.LogManager;
032import org.apache.logging.log4j.Logger;
033import org.nuxeo.ecm.core.api.CoreSession;
034import org.nuxeo.ecm.core.api.DocumentModel;
035import org.nuxeo.ecm.core.api.NuxeoException;
036import org.nuxeo.ecm.core.migrator.AbstractRepositoryMigrator;
037import org.nuxeo.ecm.core.repository.RepositoryService;
038import org.nuxeo.ecm.platform.comment.service.CommentService;
039import org.nuxeo.ecm.platform.comment.service.CommentServiceConfig;
040import org.nuxeo.ecm.platform.relations.api.Graph;
041import org.nuxeo.ecm.platform.relations.api.RelationManager;
042import org.nuxeo.ecm.platform.relations.api.ResourceAdapter;
043import org.nuxeo.ecm.platform.relations.api.Statement;
044import org.nuxeo.ecm.platform.relations.api.impl.QNameResourceImpl;
045import org.nuxeo.runtime.api.Framework;
046import org.nuxeo.runtime.migration.MigrationService.MigrationContext;
047
048/**
049 * Migrator of comments.
050 *
051 * @since 10.3
052 */
053public class CommentsMigrator extends AbstractRepositoryMigrator {
054
055    private static final Logger log = LogManager.getLogger(CommentsMigrator.class);
056
057    protected static final int BATCH_SIZE = 50;
058
059    @Override
060    protected String probeSession(CoreSession session) {
061        CommentService commentComponent = (CommentService) Framework.getRuntime().getComponent(CommentService.NAME);
062        CommentServiceConfig commentServiceConfig = commentComponent.getConfig();
063        if (commentServiceConfig != null) {
064            Graph graph = Framework.getService(RelationManager.class).getGraph(commentServiceConfig.graphName, session);
065            if (graph.getStatements().size() > 0) {
066                return MIGRATION_STATE_RELATION;
067            }
068        }
069        return MIGRATION_STATE_PROPERTY;
070    }
071
072    @Override
073    protected void migrateSession(CoreSession session) {
074        CommentService commentComponent = (CommentService) Framework.getRuntime().getComponent(CommentService.NAME);
075        CommentServiceConfig commentServiceConfig = commentComponent.getConfig();
076        if (commentServiceConfig != null) {
077            RelationManager relationManager = Framework.getService(RelationManager.class);
078            Graph graph = relationManager.getGraph(commentServiceConfig.graphName, session);
079            List<Statement> statements = graph.getStatements();
080            checkShutdownRequested();
081
082            processBatched(BATCH_SIZE, statements, statement -> migrateComments(session, relationManager, commentServiceConfig, statement),
083                    "Migrating comments");
084            reportProgress("Done", statements.size(), statements.size());
085        }
086    }
087
088    @Override
089    public String probeState() {
090        List<String> repositoryNames = Framework.getService(RepositoryService.class).getRepositoryNames();
091        if (repositoryNames.stream().map(this::probeRepository).anyMatch(isEqual(MIGRATION_STATE_RELATION))) {
092            return MIGRATION_STATE_RELATION;
093        }
094        return MIGRATION_STATE_PROPERTY;
095    }
096
097    @Override
098    public void run(String step, MigrationContext migrationContext) {
099        if (!MIGRATION_STEP_RELATION_TO_PROPERTY.equals(step)) {
100            throw new NuxeoException("Unknown migration step: " + step);
101        }
102        this.migrationContext = migrationContext;
103        reportProgress("Initializing", 0, -1); // unknown
104        List<String> repositoryNames = Framework.getService(RepositoryService.class).getRepositoryNames();
105        try {
106            repositoryNames.forEach(this::migrateRepository);
107        } catch (MigrationShutdownException e) {
108            return;
109        }
110    }
111
112    @SuppressWarnings("unchecked")
113    protected void migrateComments(CoreSession session, RelationManager relationManager, CommentServiceConfig config,
114            Statement statement) {
115        Map<String, Object> ctxMap = Collections.singletonMap(ResourceAdapter.CORE_SESSION_CONTEXT_KEY, session);
116        QNameResourceImpl object = (QNameResourceImpl) statement.getObject();
117        DocumentModel parent = (DocumentModel) relationManager.getResourceRepresentation(config.documentNamespace,
118                object, ctxMap);
119
120        QNameResourceImpl subject = (QNameResourceImpl) statement.getSubject();
121        DocumentModel comment = (DocumentModel) relationManager.getResourceRepresentation(config.commentNamespace,
122                subject, ctxMap);
123
124        if (parent != null && comment != null) {
125            comment.setPropertyValue(COMMENT_PARENT_ID, parent.getId());
126            session.saveDocument(comment);
127        } else if (parent == null && comment == null) {
128            log.debug("Documents {} and {} do not exist, they can not be migrated", object.getLocalName(),
129                    subject.getLocalName());
130        } else {
131            log.debug("Document {} does not exist, it can not be migrated",
132                    parent == null ? object.getLocalName() : subject.getLocalName());
133        }
134
135        Graph graph = relationManager.getGraph(config.graphName, session);
136        graph.remove(statement);
137    }
138
139    @Override
140    public void notifyStatusChange() {
141        CommentService commentComponent = (CommentService) Framework.getRuntime().getComponent(CommentService.NAME);
142        commentComponent.invalidateCommentManagerImplementation();
143    }
144}