source: AnnotationManagerN4J/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorAnnotations.java @ 101:7268c3ca025b

Last change on this file since 101:7268c3ca025b was 101:7268c3ca025b, checked in by casties, 9 years ago

make admin ui view of all annotations scale better.

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", "1000"));
88            int offset = getInt(form.getFirstValue("offset", "0"));
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, 0, 0);
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        int max = limit + offset;
134        for (JSONObject result : results) {
135            cnt += 1;
136            if (cnt < offset) continue;
137            rows.put(result);
138            if (limit > 0 && cnt >= max) break;
139        }
140
141        // assemble result object
142        JSONObject result = new JSONObject();
143        try {
144            result.put("rows", rows);
145            result.put("total", rows.length());
146        } catch (JSONException e) {
147            setStatus(Status.SERVER_ERROR_INTERNAL, "JSON Error");
148            return null;
149        }
150        return new JsonRepresentation(result);
151    }
152
153    /**
154     * POST with JSON content-type. Creates a new Annotation.
155     *
156     * @return
157     */
158    @Post("json")
159    public Representation doPostJson(Representation entity) {
160        logger.fine("AnnotatorAnnotations doPostJSON!");
161
162        // do authentication TODO: who's allowed to create?
163        Person authUser = getUserFromAuthToken(entity);
164        logger.fine("request authenticated=" + authUser);
165        if (authUser == null) {
166            setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
167            return null;
168        }
169
170        Annotation annot = null;
171        try {
172            JsonRepresentation jrep = new JsonRepresentation(entity);
173            JSONObject jo = jrep.getJsonObject();
174            if (jo == null) {
175                setStatus(Status.SERVER_ERROR_INTERNAL);
176                return null;
177            }
178            // make sure id is not set for POST
179            jo.remove("id");
180            // create Annotation object from posted JSON
181            annot = createAnnotation(jo, entity);
182        } catch (IOException e1) {
183            setStatus(Status.SERVER_ERROR_INTERNAL);
184            return null;
185        } catch (JSONException e) {
186            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
187            return null;
188        }
189        if (annot == null) {
190            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
191            return null;
192        }
193        Annotation storedAnnot;
194        // store Annotation
195        storedAnnot = getAnnotationStore().storeAnnotation(annot);
196        /*
197         * according to https://github.com/okfn/annotator/wiki/Storage we should
198         * return 303: see other. For now we return the annotation.
199         */
200        JSONObject jo = createAnnotatorJson(storedAnnot, (authUser == null));
201        JsonRepresentation retRep = new JsonRepresentation(jo);
202        return retRep;
203    }
204
205    /**
206     * PUT with JSON content-type. Modifies an Annotation.
207     *
208     * @param entity
209     * @return
210     */
211    @Put("json")
212    public Representation doPutJSON(Representation entity) {
213        logger.fine("AnnotatorAnnotations doPutJSON!");
214        // id from URI /annotations/{id}
215        String jsonId = (String) getRequest().getAttributes().get("id");
216        String id = decodeJsonId(jsonId);
217        logger.fine("annotation-id=" + id);
218
219        // do authentication
220        Person authUser = getUserFromAuthToken(entity);
221        logger.fine("request authenticated=" + authUser);
222
223        Annotation annot = null;
224        AnnotationStore store = getAnnotationStore();
225        try {
226            JsonRepresentation jrep = new JsonRepresentation(entity);
227            JSONObject jo = jrep.getJsonObject();
228            if (jo == null) {
229                setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
230                return null;
231            }
232            // get stored Annotation
233            Annotation storedAnnot = store.getAnnotationById(id);
234            if (storedAnnot == null) {
235                setStatus(Status.CLIENT_ERROR_NOT_FOUND);
236                return null;
237            }
238            if (!storedAnnot.isActionAllowed("update", authUser, store)) {
239                setStatus(Status.CLIENT_ERROR_FORBIDDEN);
240                return null;
241            }
242            // update from posted JSON
243            annot = updateAnnotation(storedAnnot, jo, entity);
244            // store Annotation
245            storedAnnot = store.storeAnnotation(annot);
246            /*
247             * according to https://github.com/okfn/annotator/wiki/Storage we
248             * should return 303: see other. but the client doesn't like it
249             * setStatus(Status.REDIRECTION_SEE_OTHER); // go to same URL as
250             * this one Reference thisUrl = this.getReference();
251             * this.getResponse().setLocationRef(thisUrl);
252             */
253            // return new annotation
254            jo = createAnnotatorJson(storedAnnot, (authUser == null));
255            JsonRepresentation retRep = new JsonRepresentation(jo);
256            return retRep;
257        } catch (JSONException e) {
258            logger.severe("Error in doPutJSON: "+e);
259            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
260        } catch (IOException e) {
261            logger.severe("Error in doPutJSON: "+e);
262            setStatus(Status.SERVER_ERROR_INTERNAL, "Other Error");
263        }
264        return null;
265    }
266
267    /**
268     * DELETE with JSON content-type. Deletes an Annotation.
269     *
270     * @param entity
271     * @return
272     */
273    @Delete("json")
274    public Representation doDeleteJSON(Representation entity) {
275        logger.fine("AnnotatorAnnotations doDeleteJSON!");
276        // id from URI /annotations/{id}
277        String jsonId = (String) getRequest().getAttributes().get("id");
278        String id = decodeJsonId(jsonId);
279        logger.fine("annotation-id=" + id);
280
281        // do authentication
282        Person authUser = getUserFromAuthToken(entity);
283        logger.fine("request authenticated=" + authUser);
284        AnnotationStore store = getAnnotationStore();
285        Annotation annot = store.getAnnotationById(id);
286        if (annot != null) {
287            if (!annot.isActionAllowed("delete", authUser, store)) {
288                setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
289                return null;
290            }
291        }
292        // delete annotation
293        store.deleteAnnotationById(id);
294        setStatus(Status.SUCCESS_NO_CONTENT);
295        return null;
296    }
297
298}
Note: See TracBrowser for help on using the repository browser.