001/*
002 * (C) Copyright 2006-2008 Nuxeo SA (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 *     Alexandre Russel
018 *
019 * $Id$
020 */
021
022package org.nuxeo.ecm.platform.annotations.repository.service;
023
024import java.net.URI;
025import java.util.ArrayList;
026import java.util.List;
027
028import org.apache.commons.logging.Log;
029import org.apache.commons.logging.LogFactory;
030import org.nuxeo.ecm.core.api.DocumentModel;
031import org.nuxeo.ecm.core.api.DocumentRef;
032import org.nuxeo.ecm.core.api.NuxeoPrincipal;
033import org.nuxeo.ecm.core.api.event.DocumentEventTypes;
034import org.nuxeo.ecm.core.api.facet.VersioningDocument;
035import org.nuxeo.ecm.core.event.Event;
036import org.nuxeo.ecm.core.event.EventContext;
037import org.nuxeo.ecm.platform.annotations.api.Annotation;
038import org.nuxeo.ecm.platform.annotations.api.AnnotationsConstants;
039import org.nuxeo.ecm.platform.annotations.api.AnnotationsService;
040import org.nuxeo.ecm.platform.annotations.repository.URNDocumentViewTranslator;
041import org.nuxeo.ecm.platform.relations.api.Graph;
042import org.nuxeo.ecm.platform.relations.api.Resource;
043import org.nuxeo.ecm.platform.relations.api.Statement;
044import org.nuxeo.ecm.platform.relations.api.impl.ResourceImpl;
045import org.nuxeo.ecm.platform.relations.api.impl.StatementImpl;
046import org.nuxeo.runtime.api.Framework;
047
048/**
049 * @author <a href="mailto:arussel@nuxeo.com">Alexandre Russel</a>
050 */
051public class DocumentVersionnedGraphManager implements GraphManagerEventListener {
052
053    private static final Log log = LogFactory.getLog(DocumentVersionnedGraphManager.class);
054
055    private URNDocumentViewTranslator translator;
056
057    @Override
058    public void manage(Event event) {
059        if (translator == null) {
060            translator = new URNDocumentViewTranslator();
061        }
062        EventContext context = event.getContext();
063        NuxeoPrincipal user = context.getPrincipal();
064        DocumentModel docModel = (DocumentModel) context.getArguments()[0];
065        String docId = docModel.getId();
066        String repo = docModel.getRepositoryName();
067
068        if (DocumentEventTypes.DOCUMENT_CHECKEDIN.equals(event.getName())) {
069            DocumentRef versionRef = (DocumentRef) context.getProperty("checkedInVersionRef");
070            copyGraphFor(repo, docId, versionRef.toString(), user);
071        } else if (DocumentEventTypes.DOCUMENT_REMOVED.equals(event.getName())
072                || DocumentEventTypes.VERSION_REMOVED.equals(event.getName())) {
073            removeGraphFor(repo, docId, user);
074        } else if (DocumentEventTypes.DOCUMENT_RESTORED.equals(event.getName())) {
075            String versionUUID = (String) context.getProperty(VersioningDocument.RESTORED_VERSION_UUID_KEY);
076            restoreGraphFor(repo, versionUUID, docId, user);
077        }
078    }
079
080    private void copyGraphFor(String repositoryName, String fromId, String toId, NuxeoPrincipal principal) {
081        copyGraphFor(translator.getNuxeoUrn(repositoryName, fromId), translator.getNuxeoUrn(repositoryName, toId),
082                principal);
083    }
084
085    private static void copyGraphFor(URI current, URI copied, NuxeoPrincipal user) {
086        List<Statement> newStatements = new ArrayList<Statement>();
087        AnnotationsService service = Framework.getService(AnnotationsService.class);
088        List<Annotation> annotations = service.queryAnnotations(current, user);
089        log.debug("Copying annotations graph from " + current + " to " + copied + " for " + annotations.size()
090                + " annotations.");
091        for (Annotation annotation : annotations) {
092            List<Statement> statements = annotation.getStatements();
093            for (Statement statement : statements) {
094                if (statement.getPredicate().equals(AnnotationsConstants.a_annotates)) {
095                    Resource resource = (Resource) statement.getObject();
096                    if (current.toString().equals(resource.getUri())) {
097                        // copy only the statements associated to the current
098                        // URI
099                        Statement newStatement = new StatementImpl(statement.getSubject(), statement.getPredicate(),
100                                new ResourceImpl(copied.toString()));
101                        newStatements.add(newStatement);
102                    }
103                }
104            }
105        }
106        Graph graph = service.getAnnotationGraph();
107        graph.add(newStatements);
108    }
109
110    private void removeGraphFor(String repositoryName, String id, NuxeoPrincipal principal) {
111        removeGraphFor(translator.getNuxeoUrn(repositoryName, id), principal);
112    }
113
114    private static void removeGraphFor(URI uri, NuxeoPrincipal user) {
115        log.debug("Removing annotations graph for " + uri);
116        AnnotationsService service = Framework.getService(AnnotationsService.class);
117        List<Annotation> annotations = service.queryAnnotations(uri, user);
118        for (Annotation annotation : annotations) {
119            service.deleteAnnotationFor(uri, annotation, user);
120        }
121    }
122
123    private void restoreGraphFor(String repositoryName, String versionId, String docId, NuxeoPrincipal principal) {
124        log.debug("Restoring annotations graph for docId:" + docId + " and versionId:" + versionId);
125        removeGraphFor(translator.getNuxeoUrn(repositoryName, docId), principal);
126        copyGraphFor(repositoryName, versionId, docId, principal);
127    }
128
129}