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