001/*
002 * (C) Copyright 2006-2008 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Alexandre Russel
016 *
017 * $Id$
018 */
019
020package org.nuxeo.ecm.platform.annotations.service;
021
022import java.net.URI;
023import java.util.ArrayList;
024import java.util.List;
025import java.util.Map;
026
027import org.nuxeo.ecm.core.api.NuxeoPrincipal;
028import org.nuxeo.ecm.platform.annotations.api.Annotation;
029import org.nuxeo.ecm.platform.annotations.api.AnnotationManager;
030import org.nuxeo.ecm.platform.annotations.api.AnnotationsConstants;
031import org.nuxeo.ecm.platform.annotations.api.AnnotationsService;
032import org.nuxeo.ecm.platform.annotations.api.UriResolver;
033import org.nuxeo.ecm.platform.relations.api.Graph;
034import org.nuxeo.ecm.platform.relations.api.Literal;
035import org.nuxeo.ecm.platform.relations.api.Node;
036import org.nuxeo.ecm.platform.relations.api.QueryResult;
037import org.nuxeo.ecm.platform.relations.api.RelationManager;
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
044/**
045 * @author Alexandre Russel
046 */
047public class AnnotationsServiceImpl implements AnnotationsService {
048
049    private static final String GET_ANN_QUERY = "SELECT ?p ?o WHERE { <source> ?p ?o }";
050
051    private final RelationManager relationManager;
052
053    private final AnnotationConfigurationService configuration;
054
055    private final AnnotationIDGenerator idGenerator;
056
057    private final MetadataMapper mapper;
058
059    private final UriResolver resolver;
060
061    private final AnnotationManager annotationManager = new AnnotationManager();
062
063    public AnnotationsServiceImpl() {
064        relationManager = Framework.getService(RelationManager.class);
065        configuration = Framework.getService(AnnotationConfigurationService.class);
066        idGenerator = configuration.getIDGenerator();
067        mapper = configuration.getMetadataMapper();
068        resolver = configuration.getUriResolver();
069    }
070
071    public Annotation addAnnotation(Annotation annotation, NuxeoPrincipal user, String baseUrl) {
072        String id = idGenerator.getNext();
073        return addAnnotation(annotation, user, baseUrl, id);
074    }
075
076    private Annotation addAnnotation(Annotation annotation, NuxeoPrincipal user, String baseUrl, String id) {
077        Graph graph = relationManager.getGraphByName(AnnotationsConstants.DEFAULT_GRAPH_NAME);
078        Resource resource = new ResourceImpl(AnnotationsConstants.DEFAULT_BASE_URI + id);
079        annotation.setSubject(resource);
080        mapper.updateMetadata(annotation, user);
081        graph.add(annotation.getStatements());
082        return annotation;
083
084    }
085
086    public void deleteAnnotation(Annotation annotation, NuxeoPrincipal user) {
087        Graph graph = relationManager.getGraphByName(AnnotationsConstants.DEFAULT_GRAPH_NAME);
088        graph.remove(annotation.getStatements());
089    }
090
091    public void deleteAnnotationFor(URI uri, Annotation annotation, NuxeoPrincipal user) {
092        List<Statement> statementsToDelete = new ArrayList<Statement>();
093
094        boolean removeAllAnnotationStatements = true;
095        List<Statement> statements = annotation.getStatements();
096        for (Statement statement : statements) {
097            if (statement.getPredicate().equals(AnnotationsConstants.a_annotates)) {
098                Resource resource = (Resource) statement.getObject();
099                if (uri.toString().equals(resource.getUri())) {
100                    statementsToDelete.add(statement);
101                } else {
102                    // we have another URI using these annotations statements
103                    removeAllAnnotationStatements = false;
104                }
105            }
106        }
107        if (removeAllAnnotationStatements) {
108            statementsToDelete.addAll(annotation.getStatements());
109        }
110        Graph graph = getAnnotationGraph();
111        graph.remove(statementsToDelete);
112    }
113
114    public Annotation getAnnotation(String id, NuxeoPrincipal user, String baseUrl) {
115        String uri = AnnotationsConstants.DEFAULT_BASE_URI + id;
116        String query = GET_ANN_QUERY.replaceFirst("source", uri);
117        Graph graph = relationManager.getGraphByName(AnnotationsConstants.DEFAULT_GRAPH_NAME);
118        QueryResult result = graph.query(query, "sparql", null);
119        List<Statement> statements = new ArrayList<Statement>();
120        for (Map<String, Node> map : result.getResults()) {
121            Statement statement = new StatementImpl(new ResourceImpl(uri), map.get("p"), map.get("o"));
122            statements.add(statement);
123        }
124        return annotationManager.getAnnotation(statements);
125    }
126
127    public String getAnnotationBody(String id, NuxeoPrincipal name) {
128        String uri = AnnotationsConstants.DEFAULT_BASE_URI + "body/" + id;
129        Graph graph = relationManager.getGraphByName(AnnotationsConstants.DEFAULT_GRAPH_NAME);
130        List<Node> result = graph.getObjects(new ResourceImpl(uri), AnnotationsConstants.nx_body_content);
131        return ((Literal) result.get(0)).getValue();
132    }
133
134    public List<Annotation> queryAnnotations(URI uri, NuxeoPrincipal user) {
135        AnnotationQuery query = new AnnotationQuery();
136        Graph graph = relationManager.getGraphByName(AnnotationsConstants.DEFAULT_GRAPH_NAME);
137        uri = resolver.getSearchURI(uri);
138        return query.getAnnotationsForURIs(uri, graph);
139    }
140
141    @Override
142    public int getAnnotationsCount(URI uri, NuxeoPrincipal user) {
143        AnnotationQuery query = new AnnotationQuery();
144        Graph graph = relationManager.getGraphByName(AnnotationsConstants.DEFAULT_GRAPH_NAME);
145        uri = resolver.getSearchURI(uri);
146        return query.getAnnotationsCountForURIs(uri, graph);
147    }
148
149    public Annotation updateAnnotation(Annotation annotation, NuxeoPrincipal user, String baseUrl) {
150        String id = annotation.getId();
151        deleteAnnotation(annotation, user);
152        return addAnnotation(annotation, user, baseUrl, id);
153    }
154
155    public Graph getAnnotationGraph() {
156        return relationManager.getGraphByName(AnnotationsConstants.DEFAULT_GRAPH_NAME);
157    }
158
159}