source: AnnotationManagerN4J/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorAnnotations.java @ 3:47b53ae385d1

Last change on this file since 3:47b53ae385d1 was 3:47b53ae385d1, checked in by casties, 12 years ago

merging old code

File size: 14.7 KB
Line 
1/**
2 * Implements the "annotations" uri of the Annotator API. see
3 * <https://github.com/okfn/annotator/wiki/Storage>
4 */
5package de.mpiwg.itgroup.annotations.restlet;
6
7import java.io.IOException;
8import java.util.ArrayList;
9import java.util.List;
10
11import org.json.JSONArray;
12import org.json.JSONException;
13import org.json.JSONObject;
14import org.restlet.Context;
15import org.restlet.data.Form;
16import org.restlet.data.MediaType;
17import org.restlet.data.Reference;
18import org.restlet.data.Status;
19import org.restlet.ext.json.JsonRepresentation;
20import org.restlet.representation.Representation;
21import org.restlet.representation.StringRepresentation;
22import org.restlet.resource.Delete;
23import org.restlet.resource.Get;
24import org.restlet.resource.Post;
25import org.restlet.resource.Put;
26import org.restlet.security.User;
27
28import de.mpiwg.itgroup.annotationManager.Constants.NS;
29import de.mpiwg.itgroup.annotationManager.Errors.TripleStoreSearchError;
30import de.mpiwg.itgroup.annotationManager.Errors.TripleStoreStoreError;
31import de.mpiwg.itgroup.annotationManager.RDFHandling.Annotation;
32import de.mpiwg.itgroup.annotationManager.RDFHandling.Convert;
33import de.mpiwg.itgroup.annotationManager.RDFHandling.RDFSearcher;
34import de.mpiwg.itgroup.annotationManager.drupal.AnnotationHandler;
35import de.mpiwg.itgroup.annotationManager.drupal.UnknowUserException;
36import de.mpiwg.itgroup.triplestoremanager.exceptions.TripleStoreHandlerException;
37
38/**
39 * Implements the "annotations" uri of the Annotator API. see <https://github.com/okfn/annotator/wiki/Storage>
40 *
41 * @author dwinter, casties
42 *
43 */
44public class AnnotatorAnnotations extends AnnotatorResourceImpl {
45
46    protected String getAllowedMethodsForHeader() {
47        return "OPTIONS,GET,POST,PUT,DELETE";
48    }
49
50    /**
51     * GET with JSON content-type.
52     *
53     * @param entity
54     * @return
55     */
56    @Get("json")
57    public Representation doGetJSON(Representation entity) {
58        logger.debug("AnnotatorAnnotations doGetJSON!");
59        setCorsHeaders();
60        // id from URI /annotations/{id}
61        String jsonId = (String) getRequest().getAttributes().get("id");
62        String id = decodeJsonId(jsonId);
63        logger.debug("annotation-id=" + id);
64
65        // TODO: what to return without id - list of all annotations?
66
67        // TODO: what to do with authentication?
68        boolean authenticated = isAuthenticated(entity);
69        logger.debug("request authenticated=" + authenticated);
70
71        RDFSearcher searcher = new RDFSearcher(NS.MPIWG_ANNOT_CTX); // TODO should ge into config file
72
73        try {
74            List<Annotation> annots = searcher.searchById(id);
75            if (annots.size() == 1) {
76                // there should be only one
77                JSONObject result = createAnnotatorJson(annots.get(0));
78                logger.debug("sending:");
79                logger.debug(result);
80                return new JsonRepresentation(result);
81            } else {
82                JSONArray results;
83                results = new JSONArray();
84                for (Annotation annot : annots) {
85                    JSONObject jo = createAnnotatorJson(annot);
86                    if (jo != null) {
87                        results.put(createAnnotatorJson(annot));
88                    } else {
89                        setStatus(Status.SERVER_ERROR_INTERNAL, "JSon Error");
90                        return null;
91                    }
92                }
93                // annotator read request returns a list of annotation objects
94                logger.debug("sending:");
95                logger.debug(results);
96                return new JsonRepresentation(results);
97            }
98        } catch (TripleStoreHandlerException e) {
99            e.printStackTrace();
100            setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStoreHandler Error");
101            return null;
102        } catch (TripleStoreSearchError e) {
103            e.printStackTrace();
104            setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStoreSearch Error");
105            return null;
106        }
107    }
108
109    /**
110     * POST with JSON content-type.
111     *
112     * json hash: username: name des users xpointer: xpointer auf den Ausschnitt (incl. der URL des Dokumentes) text: text der
113     * annotation annoturl: url auf eine Annotation falls extern
114     *
115     * @return
116     */
117    @Post("json")
118    public Representation doPostJson(Representation entity) {
119        logger.debug("AnnotatorAnnotations doPostJSON!");
120        // set headers
121        setCorsHeaders();
122        Annotation annot = null;
123        try {
124            JsonRepresentation jrep = new JsonRepresentation(entity);
125            JSONObject jo = jrep.getJsonObject();
126            if (jo == null) {
127                setStatus(Status.SERVER_ERROR_INTERNAL);
128                return null;
129            }
130            // make sure id is not set for POST
131            jo.remove("id");
132            // get Annotation object from posted JSON
133            annot = createAnnotation(jo, entity);
134        } catch (IOException e1) {
135            setStatus(Status.SERVER_ERROR_INTERNAL);
136            return null;
137        } catch (JSONException e) {
138            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
139            return null;
140        }
141        if (annot == null || annot.xpointer == null || annot.creator == null) {
142            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
143            return null;
144        }
145        Annotation storedAnnot;
146        try {
147            // store Annotation
148            storedAnnot = new Convert(NS.MPIWG_ANNOT_CTX).storeAnnotation(annot);
149        } catch (TripleStoreStoreError e) {
150            e.printStackTrace();
151            setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStore Error");
152            return null;
153        }
154        /* according to https://github.com/okfn/annotator/wiki/Storage
155         * we should return 303: see other.
156         * For now we return the annotation.
157         */
158        JSONObject jo = createAnnotatorJson(storedAnnot);
159        JsonRepresentation retRep = new JsonRepresentation(jo);
160        return retRep;
161    }
162
163    /**
164     * POST with HTML content-type.
165     *
166     * @param entity
167     * @return
168     */
169    @Post("html")
170    public Representation doPostHtml(Representation entity) {
171        logger.debug("AnnotatorAnnotations doPostHtml!");
172        Annotation annot;
173        annot = handleForm(entity);
174        if (annot.xpointer == null || annot.creator == null) {
175            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
176
177            return null;
178        }
179
180        Annotation retValAnnot;
181        try {
182            retValAnnot = new Convert(NS.MPIWG_ANNOT_CTX).storeAnnotation(annot);
183        } catch (TripleStoreStoreError e) {
184            e.printStackTrace();
185            setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStore Error");
186            return null;
187        }
188        if (retValAnnot == null) {
189            return null;
190        }
191        String retVal = retValAnnot.getAnnotationUri();
192        if (retVal == null) {
193            return null;
194        }
195
196        String text = String.format("<html><body><a href=\"%s\">%s</a></body></html>", retVal.replace(">", "").replace("<", ""),
197                retVal.replace(">", "&gt;").replace("<", "&lt;"));
198        Representation retRep = new StringRepresentation(text, MediaType.TEXT_HTML);
199        return retRep;
200    }
201
202    /**
203     *
204     * @param entity
205     *            should contain a form with the parameters "username", "password", "xpointer","text","uri","type"
206     *
207     *            username,password is optional, if not given BasicAuthentification is used.
208     *
209     *            If username given as a URI, the username will be transformed to an URI, username will be added to the MPIWG
210     *            namespace defined in de.mpiwg.itgroup.annotationManager.Constants.NS
211     *
212     * @return
213     */
214    protected Annotation handleForm(Representation entity) {
215        Annotation annot;
216        Form form = new Form(entity);
217        String username = form.getValues("username");
218        String mode = form.getValues("mode");
219        String password = form.getValues("password");
220        String xpointer = form.getValues("xpointer");
221        String text = form.getValues("text");
222        String title = form.getValues("title");
223        String url = form.getValues("url");
224        String type = form.getValues("type");
225        RestServer restServer = (RestServer) getApplication();
226
227        // falls user and password nicht null sind:
228        User userFromForm = null;
229        if (username != null && password != null) {
230            if (restServer.authenticate(username, password, getRequest())) {
231                userFromForm = new User(username);
232            }
233        }
234        User authUser = null;
235
236        if (userFromForm == null) {
237            authUser = getHttpAuthUser(entity);
238        }
239
240        // weder BasicAuth noch FormAuth
241        if (authUser == null && userFromForm == null) {
242            setStatus(Status.CLIENT_ERROR_FORBIDDEN);
243            return null;
244        }
245
246        if (userFromForm != null) {
247            username = userFromForm.getIdentifier();
248        } else {
249            username = authUser.getIdentifier();
250        }
251
252        // username should be a URI, if not it will set to the MPIWG namespace defined in
253        // de.mpiwg.itgroup.annotationManager.Constants.NS
254        String usernameOrig = username;
255        if (!username.startsWith("http"))
256            username = NS.MPIWG_PERSONS_URL + username;
257
258        if (mode.equals("complexAnnotation")) {// Annotation mit text in externer ressource
259
260            Context context = getContext();
261            String drupalPath = context.getParameters().getFirstValue("de.mpiwg.itgroup.annotationManager.drupalServer");
262
263            AnnotationHandler ah = new AnnotationHandler(drupalPath);
264            JSONObject newAnnot;
265            try {
266                newAnnot = ah.createAnnotation(title, text, usernameOrig, password);
267            } catch (UnknowUserException e1) {
268                setStatus(Status.CLIENT_ERROR_FORBIDDEN);
269                e1.printStackTrace();
270                return null;
271            }
272            try {
273                annot = new Annotation(xpointer, username, null, text, type, newAnnot.getString("node_uri"));
274            } catch (JSONException e) {
275                // TODO Auto-generated catch block
276                e.printStackTrace();
277                setStatus(Status.SERVER_ERROR_INTERNAL);
278                return null;
279            }
280        } else
281            annot = new Annotation(xpointer, username, null, text, type, url);
282        return annot;
283    }
284
285
286    /**
287     * PUT with JSON content-type.
288     *
289     * @param entity
290     * @return
291     */
292    @Put("json")
293    public Representation doPutJSON(Representation entity) {
294        logger.debug("AnnotatorAnnotations doPutJSON!");
295        setCorsHeaders();
296        // id from URI /annotations/{id}
297        String jsonId = (String) getRequest().getAttributes().get("id");
298        String id = decodeJsonId(jsonId);
299        logger.debug("annotation-id=" + id);
300
301        // TODO: what to do with authentication? we should check the owner
302        boolean authenticated = isAuthenticated(entity);
303        logger.debug("request authenticated=" + authenticated);
304        if (!authenticated) {
305            setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
306            return null;           
307        }
308
309        Annotation annot = null;
310        try {
311            JsonRepresentation jrep = new JsonRepresentation(entity);
312            JSONObject jo = jrep.getJsonObject();
313            if (jo == null) {
314                setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
315                return null;
316            }
317            RDFSearcher searcher = new RDFSearcher(NS.MPIWG_ANNOT_CTX); // TODO should ge into config file
318            // get stored Annotation
319            List<Annotation> annots = searcher.searchById(id);
320            if (annots.size() < 1) {
321                setStatus(Status.CLIENT_ERROR_NOT_FOUND);
322                return null;
323            }
324            Annotation storedAnnot = annots.get(0);
325            // delete
326            searcher.deleteById(id);
327            // update from posted JSON
328            annot = updateAnnotation(storedAnnot, jo, entity);
329            // store Annotation
330            storedAnnot = new Convert(NS.MPIWG_ANNOT_CTX).storeAnnotation(annot);
331            /* according to https://github.com/okfn/annotator/wiki/Storage
332             * we should return 303: see other.
333             * but the client doesn't like it
334            setStatus(Status.REDIRECTION_SEE_OTHER);
335            // go to same URL as this one
336            Reference thisUrl = this.getReference();
337            this.getResponse().setLocationRef(thisUrl); */
338            // return new annotation
339            jo = createAnnotatorJson(storedAnnot);
340            JsonRepresentation retRep = new JsonRepresentation(jo);
341            return retRep;
342        } catch (TripleStoreHandlerException e) {
343            e.printStackTrace();
344            setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStoreHandler Error");
345        } catch (TripleStoreSearchError e) {
346            e.printStackTrace();
347            setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStoreSearch Error");
348        } catch (JSONException e) {
349            e.printStackTrace();
350            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
351        } catch (IOException e) {
352            e.printStackTrace();
353            setStatus(Status.SERVER_ERROR_INTERNAL, "Other Error");
354        }
355        return null;
356    }
357
358    /**
359     * DELETE with JSON content-type.
360     *
361     * @param entity
362     * @return
363     */
364    @Delete("json")
365    public Representation doDeleteJSON(Representation entity) {
366        logger.debug("AnnotatorAnnotations doDeleteJSON!");
367        setCorsHeaders();
368        // id from URI /annotations/{id}
369        String jsonId = (String) getRequest().getAttributes().get("id");
370        String id = decodeJsonId(jsonId);
371        logger.debug("annotation-id=" + id);
372
373        // TODO: what to do with authentication? we should check the owner
374        boolean authenticated = isAuthenticated(entity);
375        logger.debug("request authenticated=" + authenticated);
376        if (!authenticated) {
377            setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
378            return null;           
379        }
380       
381        RDFSearcher searcher = new RDFSearcher(NS.MPIWG_ANNOT_CTX); // TODO should ge into config file
382
383        try {
384            // delete annotation
385            searcher.deleteById(id);
386            setStatus(Status.SUCCESS_NO_CONTENT);
387        } catch (TripleStoreHandlerException e) {
388            e.printStackTrace();
389            setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStoreHandler Error");
390        } catch (TripleStoreSearchError e) {
391            e.printStackTrace();
392            setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStoreSearch Error");
393        }
394        return null;
395    }
396   
397
398}
Note: See TracBrowser for help on using the repository browser.