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 *     Nour AL KOTOB
018 */
019package org.nuxeo.ecm.platform.routing.core.listener;
020
021import static org.nuxeo.ecm.platform.routing.api.DocumentRoutingConstants.ATTACHED_DOCUMENTS_PROPERTY_NAME;
022import static org.nuxeo.ecm.platform.routing.api.DocumentRoutingConstants.DOCUMENT_ROUTE_DOCUMENT_TYPE;
023import static org.nuxeo.ecm.platform.routing.api.DocumentRoutingConstants.ROUTING_TASK_DOC_TYPE;
024
025import java.io.Serializable;
026import java.util.List;
027
028import org.nuxeo.ecm.core.api.CoreSession;
029import org.nuxeo.ecm.core.api.DocumentModel;
030import org.nuxeo.ecm.core.event.Event;
031import org.nuxeo.ecm.core.event.EventBundle;
032import org.nuxeo.ecm.core.event.PostCommitEventListener;
033import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
034import org.nuxeo.ecm.platform.routing.api.DocumentRoute;
035import org.nuxeo.ecm.platform.routing.api.DocumentRoutingConstants;
036
037/**
038 * Listener that deletes orphan DocumentRoutes.
039 *
040 * @since 11.2
041 */
042public class DocumentRouteOrphanedListener implements PostCommitEventListener {
043
044    protected static final String QUERY_GET_RELATED_DOCUMENT_ROUTES = "SELECT * FROM " + DOCUMENT_ROUTE_DOCUMENT_TYPE
045            + " WHERE " + ATTACHED_DOCUMENTS_PROPERTY_NAME + " = '%s'";
046
047    @Override
048    public void handleEvent(EventBundle events) {
049        for (Event event : events) {
050            DocumentEventContext context = (DocumentEventContext) event.getContext();
051            DocumentModel docModel = context.getSourceDocument();
052            if (!DOCUMENT_ROUTE_DOCUMENT_TYPE.equals(docModel.getType())
053                    && !ROUTING_TASK_DOC_TYPE.equals(docModel.getType())) {
054                deleteOrphanDocumentRoutes(context.getCoreSession(), docModel.getId());
055            }
056        }
057    }
058
059    /**
060     * Removes the given id from DocumentRoutes attached documents list and deletes the DocumentRoutes if they are not
061     * attached to a document anymore.
062     */
063    protected void deleteOrphanDocumentRoutes(CoreSession session, String id) {
064        String query = String.format(QUERY_GET_RELATED_DOCUMENT_ROUTES, id);
065        for (DocumentModel doc : session.query(query)) {
066            @SuppressWarnings("unchecked")
067            var attachedDocuments = (List<String>) doc.getPropertyValue(ATTACHED_DOCUMENTS_PROPERTY_NAME);
068            attachedDocuments.remove(id);
069            if (attachedDocuments.isEmpty()) {
070                session.removeDocument(doc.getRef());
071            } else {
072                doc.setPropertyValue(ATTACHED_DOCUMENTS_PROPERTY_NAME, (Serializable) attachedDocuments);
073                session.saveDocument(doc);
074            }
075        }
076    }
077
078}