Mercurial > hg > AnnotationManagerN4J
comparison src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorAnnotations.java @ 3:47b53ae385d1
merging old code
author | casties |
---|---|
date | Fri, 29 Jun 2012 20:38:27 +0200 |
parents | |
children | 3599b29c393f |
comparison
equal
deleted
inserted
replaced
2:f2d44c41eedf | 3:47b53ae385d1 |
---|---|
1 /** | |
2 * Implements the "annotations" uri of the Annotator API. see | |
3 * <https://github.com/okfn/annotator/wiki/Storage> | |
4 */ | |
5 package de.mpiwg.itgroup.annotations.restlet; | |
6 | |
7 import java.io.IOException; | |
8 import java.util.ArrayList; | |
9 import java.util.List; | |
10 | |
11 import org.json.JSONArray; | |
12 import org.json.JSONException; | |
13 import org.json.JSONObject; | |
14 import org.restlet.Context; | |
15 import org.restlet.data.Form; | |
16 import org.restlet.data.MediaType; | |
17 import org.restlet.data.Reference; | |
18 import org.restlet.data.Status; | |
19 import org.restlet.ext.json.JsonRepresentation; | |
20 import org.restlet.representation.Representation; | |
21 import org.restlet.representation.StringRepresentation; | |
22 import org.restlet.resource.Delete; | |
23 import org.restlet.resource.Get; | |
24 import org.restlet.resource.Post; | |
25 import org.restlet.resource.Put; | |
26 import org.restlet.security.User; | |
27 | |
28 import de.mpiwg.itgroup.annotationManager.Constants.NS; | |
29 import de.mpiwg.itgroup.annotationManager.Errors.TripleStoreSearchError; | |
30 import de.mpiwg.itgroup.annotationManager.Errors.TripleStoreStoreError; | |
31 import de.mpiwg.itgroup.annotationManager.RDFHandling.Annotation; | |
32 import de.mpiwg.itgroup.annotationManager.RDFHandling.Convert; | |
33 import de.mpiwg.itgroup.annotationManager.RDFHandling.RDFSearcher; | |
34 import de.mpiwg.itgroup.annotationManager.drupal.AnnotationHandler; | |
35 import de.mpiwg.itgroup.annotationManager.drupal.UnknowUserException; | |
36 import 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 */ | |
44 public 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(">", ">").replace("<", "<")); | |
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 } |