source: AnnotationManagerN4J/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorAnnotations.java @ 91:cf44d9e1a4a7

Last change on this file since 91:cf44d9e1a4a7 was 91:cf44d9e1a4a7, checked in by casties, 9 years ago

let CORS be handled by Restlet 2.3 CorsFilter?.

File size: 10.4 KB
Line 
1package de.mpiwg.itgroup.annotations.restlet;
2
3/*
4 * #%L
5 * AnnotationManager
6 * %%
7 * Copyright (C) 2012 - 2014 MPIWG Berlin
8 * %%
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as
11 * published by the Free Software Foundation, either version 3 of the
12 * License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Lesser Public License for more details.
18 *
19 * You should have received a copy of the GNU General Lesser Public
20 * License along with this program.  If not, see
21 * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22 * #L%
23 */
24
25import java.io.IOException;
26import java.io.UnsupportedEncodingException;
27import java.net.URLDecoder;
28import java.util.ArrayList;
29import java.util.List;
30
31import org.json.JSONArray;
32import org.json.JSONException;
33import org.json.JSONObject;
34import org.restlet.data.Form;
35import org.restlet.data.Status;
36import org.restlet.ext.json.JsonRepresentation;
37import org.restlet.representation.Representation;
38import org.restlet.resource.Delete;
39import org.restlet.resource.Get;
40import org.restlet.resource.Post;
41import org.restlet.resource.Put;
42
43import de.mpiwg.itgroup.annotations.Annotation;
44import de.mpiwg.itgroup.annotations.Person;
45import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore;
46import de.mpiwg.itgroup.annotations.restlet.utils.JSONObjectComparator;
47
48/**
49 * Implements the "annotations" uri of the Annotator API. see
50 * <https://github.com/okfn/annotator/wiki/Storage>
51 *
52 * @author dwinter, casties
53 *
54 */
55public class AnnotatorAnnotations extends AnnotatorResourceImpl {
56
57    /**
58     * GET with JSON content-type.
59     *
60     * @param entity
61     * @return
62     */
63    @Get("json")
64    public Representation doGetJSON(Representation entity) {
65        logger.fine("AnnotatorAnnotations doGetJSON!");
66        // id from URI /annotations/{id}
67        String id = null;
68        String jsonId = (String) getRequest().getAttributes().get("id");
69        if (jsonId != null) {
70            // URL decode
71            try {
72                jsonId = URLDecoder.decode(jsonId, "UTF-8");
73            } catch (UnsupportedEncodingException e) {
74                // this shouldn't happen
75            }
76            id = decodeJsonId(jsonId);
77            logger.fine("annotation-id=" + id);
78        }
79
80        // do authentication
81        Person authUser = getUserFromAuthToken(entity);
82        logger.fine("request authenticated=" + authUser);
83
84        if (id == null) {
85            // no id -- send all annotations
86            Form form = getRequest().getResourceRef().getQueryAsForm();
87            int limit = getInt(form.getFirstValue("limit"));
88            int offset = getInt(form.getFirstValue("offset"));
89            String sortBy = form.getFirstValue("sortBy");
90            return getAllAnnotations(authUser, limit, offset, sortBy);
91        }
92
93        // send annotation with id
94        AnnotationStore store = getAnnotationStore();
95        Annotation annot = store.getAnnotationById(id);
96        if (annot != null) {
97            if (!annot.isActionAllowed("read", authUser, store)) {
98                setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
99                return null;
100            }
101            JSONObject result = createAnnotatorJson(annot, (authUser == null));
102            return new JsonRepresentation(result);
103        } else {
104            // not found
105            setStatus(Status.CLIENT_ERROR_NOT_FOUND);
106            return null;
107        }
108    }
109
110    private Representation getAllAnnotations(Person authUser, int limit, int offset, String sortBy) {
111        AnnotationStore store = getAnnotationStore();
112        ArrayList<JSONObject> results = new ArrayList<JSONObject>();
113
114        // read all annotations
115        List<Annotation> annotations = store.getAnnotations(null, null);
116        for (Annotation annotation : annotations) {
117            // check permission
118            if (!annotation.isActionAllowed("read", authUser, store))
119                continue;
120            // add annotation to list
121            JSONObject jo = createAnnotatorJson(annotation, false);
122            results.add(jo);
123        }
124
125        // sort if necessary
126        if (sortBy != null) {
127            JSONObjectComparator.sortAnnotations(results, sortBy);
128        }
129
130        // put in JSON list
131        JSONArray rows = new JSONArray();
132        int cnt = 0;
133        for (JSONObject result : results) {
134            cnt += 1;
135            if (offset > 0 && cnt < offset)
136                continue;
137            rows.put(result);
138            if (limit > 0 && cnt >= limit)
139                break;
140        }
141
142        // assemble result object
143        JSONObject result = new JSONObject();
144        try {
145            result.put("rows", rows);
146            result.put("total", rows.length());
147        } catch (JSONException e) {
148            setStatus(Status.SERVER_ERROR_INTERNAL, "JSON Error");
149            return null;
150        }
151        return new JsonRepresentation(result);
152    }
153
154    /**
155     * POST with JSON content-type. Creates a new Annotation.
156     *
157     * @return
158     */
159    @Post("json")
160    public Representation doPostJson(Representation entity) {
161        logger.fine("AnnotatorAnnotations doPostJSON!");
162
163        // do authentication TODO: who's allowed to create?
164        Person authUser = getUserFromAuthToken(entity);
165        logger.fine("request authenticated=" + authUser);
166        if (authUser == null) {
167            setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
168            return null;
169        }
170
171        Annotation annot = null;
172        try {
173            JsonRepresentation jrep = new JsonRepresentation(entity);
174            JSONObject jo = jrep.getJsonObject();
175            if (jo == null) {
176                setStatus(Status.SERVER_ERROR_INTERNAL);
177                return null;
178            }
179            // make sure id is not set for POST
180            jo.remove("id");
181            // create Annotation object from posted JSON
182            annot = createAnnotation(jo, entity);
183        } catch (IOException e1) {
184            setStatus(Status.SERVER_ERROR_INTERNAL);
185            return null;
186        } catch (JSONException e) {
187            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
188            return null;
189        }
190        if (annot == null) {
191            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
192            return null;
193        }
194        Annotation storedAnnot;
195        // store Annotation
196        storedAnnot = getAnnotationStore().storeAnnotation(annot);
197        /*
198         * according to https://github.com/okfn/annotator/wiki/Storage we should
199         * return 303: see other. For now we return the annotation.
200         */
201        JSONObject jo = createAnnotatorJson(storedAnnot, (authUser == null));
202        JsonRepresentation retRep = new JsonRepresentation(jo);
203        return retRep;
204    }
205
206    /**
207     * PUT with JSON content-type. Modifies an Annotation.
208     *
209     * @param entity
210     * @return
211     */
212    @Put("json")
213    public Representation doPutJSON(Representation entity) {
214        logger.fine("AnnotatorAnnotations doPutJSON!");
215        // id from URI /annotations/{id}
216        String jsonId = (String) getRequest().getAttributes().get("id");
217        String id = decodeJsonId(jsonId);
218        logger.fine("annotation-id=" + id);
219
220        // do authentication
221        Person authUser = getUserFromAuthToken(entity);
222        logger.fine("request authenticated=" + authUser);
223
224        Annotation annot = null;
225        AnnotationStore store = getAnnotationStore();
226        try {
227            JsonRepresentation jrep = new JsonRepresentation(entity);
228            JSONObject jo = jrep.getJsonObject();
229            if (jo == null) {
230                setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
231                return null;
232            }
233            // get stored Annotation
234            Annotation storedAnnot = store.getAnnotationById(id);
235            if (storedAnnot == null) {
236                setStatus(Status.CLIENT_ERROR_NOT_FOUND);
237                return null;
238            }
239            if (!storedAnnot.isActionAllowed("update", authUser, store)) {
240                setStatus(Status.CLIENT_ERROR_FORBIDDEN);
241                return null;
242            }
243            // update from posted JSON
244            annot = updateAnnotation(storedAnnot, jo, entity);
245            // store Annotation
246            storedAnnot = store.storeAnnotation(annot);
247            /*
248             * according to https://github.com/okfn/annotator/wiki/Storage we
249             * should return 303: see other. but the client doesn't like it
250             * setStatus(Status.REDIRECTION_SEE_OTHER); // go to same URL as
251             * this one Reference thisUrl = this.getReference();
252             * this.getResponse().setLocationRef(thisUrl);
253             */
254            // return new annotation
255            jo = createAnnotatorJson(storedAnnot, (authUser == null));
256            JsonRepresentation retRep = new JsonRepresentation(jo);
257            return retRep;
258        } catch (JSONException e) {
259            logger.severe("Error in doPutJSON: "+e);
260            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
261        } catch (IOException e) {
262            logger.severe("Error in doPutJSON: "+e);
263            setStatus(Status.SERVER_ERROR_INTERNAL, "Other Error");
264        }
265        return null;
266    }
267
268    /**
269     * DELETE with JSON content-type. Deletes an Annotation.
270     *
271     * @param entity
272     * @return
273     */
274    @Delete("json")
275    public Representation doDeleteJSON(Representation entity) {
276        logger.fine("AnnotatorAnnotations doDeleteJSON!");
277        // id from URI /annotations/{id}
278        String jsonId = (String) getRequest().getAttributes().get("id");
279        String id = decodeJsonId(jsonId);
280        logger.fine("annotation-id=" + id);
281
282        // do authentication
283        Person authUser = getUserFromAuthToken(entity);
284        logger.fine("request authenticated=" + authUser);
285        AnnotationStore store = getAnnotationStore();
286        Annotation annot = store.getAnnotationById(id);
287        if (annot != null) {
288            if (!annot.isActionAllowed("delete", authUser, store)) {
289                setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
290                return null;
291            }
292        }
293        // delete annotation
294        store.deleteAnnotationById(id);
295        setStatus(Status.SUCCESS_NO_CONTENT);
296        return null;
297    }
298
299}
Note: See TracBrowser for help on using the repository browser.