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.service;
023
024import java.net.URI;
025import java.util.ArrayList;
026import java.util.List;
027import java.util.Map;
028
029import org.nuxeo.ecm.core.api.NuxeoPrincipal;
030import org.nuxeo.ecm.platform.annotations.api.Annotation;
031import org.nuxeo.ecm.platform.annotations.api.AnnotationManager;
032import org.nuxeo.ecm.platform.annotations.api.AnnotationsConstants;
033import org.nuxeo.ecm.platform.annotations.api.AnnotationsService;
034import org.nuxeo.ecm.platform.annotations.api.UriResolver;
035import org.nuxeo.ecm.platform.relations.api.Graph;
036import org.nuxeo.ecm.platform.relations.api.Literal;
037import org.nuxeo.ecm.platform.relations.api.Node;
038import org.nuxeo.ecm.platform.relations.api.QueryResult;
039import org.nuxeo.ecm.platform.relations.api.RelationManager;
040import org.nuxeo.ecm.platform.relations.api.Resource;
041import org.nuxeo.ecm.platform.relations.api.Statement;
042import org.nuxeo.ecm.platform.relations.api.impl.ResourceImpl;
043import org.nuxeo.ecm.platform.relations.api.impl.StatementImpl;
044import org.nuxeo.runtime.api.Framework;
045
046/**
047 * @author Alexandre Russel
048 */
049public class AnnotationsServiceImpl implements AnnotationsService {
050
051    private static final String GET_ANN_QUERY = "SELECT ?p ?o WHERE { <source> ?p ?o }";
052
053    private final RelationManager relationManager;
054
055    private final AnnotationConfigurationService configuration;
056
057    private final AnnotationIDGenerator idGenerator;
058
059    private final MetadataMapper mapper;
060
061    private final UriResolver resolver;
062
063    private final AnnotationManager annotationManager = new AnnotationManager();
064
065    public AnnotationsServiceImpl() {
066        relationManager = Framework.getService(RelationManager.class);
067        configuration = Framework.getService(AnnotationConfigurationService.class);
068        idGenerator = configuration.getIDGenerator();
069        mapper = configuration.getMetadataMapper();
070        resolver = configuration.getUriResolver();
071    }
072
073    public Annotation addAnnotation(Annotation annotation, NuxeoPrincipal user, String baseUrl) {
074        String id = idGenerator.getNext();
075        return addAnnotation(annotation, user, baseUrl, id);
076    }
077
078    private Annotation addAnnotation(Annotation annotation, NuxeoPrincipal user, String baseUrl, String id) {
079        Graph graph = relationManager.getGraphByName(AnnotationsConstants.DEFAULT_GRAPH_NAME);
080        Resource resource = new ResourceImpl(AnnotationsConstants.DEFAULT_BASE_URI + id);
081        annotation.setSubject(resource);
082        mapper.updateMetadata(annotation, user);
083        graph.add(annotation.getStatements());
084        return annotation;
085
086    }
087
088    public void deleteAnnotation(Annotation annotation, NuxeoPrincipal user) {
089        Graph graph = relationManager.getGraphByName(AnnotationsConstants.DEFAULT_GRAPH_NAME);
090        graph.remove(annotation.getStatements());
091    }
092
093    public void deleteAnnotationFor(URI uri, Annotation annotation, NuxeoPrincipal user) {
094        List<Statement> statementsToDelete = new ArrayList<Statement>();
095
096        boolean removeAllAnnotationStatements = true;
097        List<Statement> statements = annotation.getStatements();
098        for (Statement statement : statements) {
099            if (statement.getPredicate().equals(AnnotationsConstants.a_annotates)) {
100                Resource resource = (Resource) statement.getObject();
101                if (uri.toString().equals(resource.getUri())) {
102                    statementsToDelete.add(statement);
103                } else {
104                    // we have another URI using these annotations statements
105                    removeAllAnnotationStatements = false;
106                }
107            }
108        }
109        if (removeAllAnnotationStatements) {
110            statementsToDelete.addAll(annotation.getStatements());
111        }
112        Graph graph = getAnnotationGraph();
113        graph.remove(statementsToDelete);
114    }
115
116    public Annotation getAnnotation(String id, NuxeoPrincipal user, String baseUrl) {
117        String uri = AnnotationsConstants.DEFAULT_BASE_URI + id;
118        String query = GET_ANN_QUERY.replaceFirst("source", uri);
119        Graph graph = relationManager.getGraphByName(AnnotationsConstants.DEFAULT_GRAPH_NAME);
120        QueryResult result = graph.query(query, "sparql", null);
121        List<Statement> statements = new ArrayList<Statement>();
122        for (Map<String, Node> map : result.getResults()) {
123            Statement statement = new StatementImpl(new ResourceImpl(uri), map.get("p"), map.get("o"));
124            statements.add(statement);
125        }
126        return annotationManager.getAnnotation(statements);
127    }
128
129    public String getAnnotationBody(String id, NuxeoPrincipal name) {
130        String uri = AnnotationsConstants.DEFAULT_BASE_URI + "body/" + id;
131        Graph graph = relationManager.getGraphByName(AnnotationsConstants.DEFAULT_GRAPH_NAME);
132        List<Node> result = graph.getObjects(new ResourceImpl(uri), AnnotationsConstants.nx_body_content);
133        return ((Literal) result.get(0)).getValue();
134    }
135
136    public List<Annotation> queryAnnotations(URI uri, NuxeoPrincipal user) {
137        AnnotationQuery query = new AnnotationQuery();
138        Graph graph = relationManager.getGraphByName(AnnotationsConstants.DEFAULT_GRAPH_NAME);
139        uri = resolver.getSearchURI(uri);
140        return query.getAnnotationsForURIs(uri, graph);
141    }
142
143    @Override
144    public int getAnnotationsCount(URI uri, NuxeoPrincipal user) {
145        AnnotationQuery query = new AnnotationQuery();
146        Graph graph = relationManager.getGraphByName(AnnotationsConstants.DEFAULT_GRAPH_NAME);
147        uri = resolver.getSearchURI(uri);
148        return query.getAnnotationsCountForURIs(uri, graph);
149    }
150
151    public Annotation updateAnnotation(Annotation annotation, NuxeoPrincipal user, String baseUrl) {
152        String id = annotation.getId();
153        deleteAnnotation(annotation, user);
154        return addAnnotation(annotation, user, baseUrl, id);
155    }
156
157    public Graph getAnnotationGraph() {
158        return relationManager.getGraphByName(AnnotationsConstants.DEFAULT_GRAPH_NAME);
159    }
160
161}