0
|
1 //TODO: handle XML-Post des Annoteaprotocolls http://www.w3.org/2001/Annotea/User/Protocol.html
|
|
2
|
|
3 package de.mpiwg.itgroup.annotationManager.restlet;
|
|
4
|
|
5 import java.io.IOException;
|
|
6 import java.io.UnsupportedEncodingException;
|
|
7 import java.net.URLDecoder;
|
|
8 import java.net.URLEncoder;
|
|
9 import java.util.ArrayList;
|
|
10 import java.util.List;
|
|
11 import java.util.regex.Matcher;
|
|
12 import java.util.regex.Pattern;
|
|
13
|
|
14 import org.apache.log4j.Logger;
|
|
15 import org.json.JSONArray;
|
|
16 import org.json.JSONException;
|
|
17 import org.json.JSONObject;
|
5
|
18 import org.restlet.Context;
|
0
|
19 import org.restlet.data.ClientInfo;
|
|
20 import org.restlet.data.Form;
|
|
21 import org.restlet.data.MediaType;
|
|
22 import org.restlet.data.Status;
|
|
23 import org.restlet.ext.json.JsonRepresentation;
|
|
24 import org.restlet.representation.Representation;
|
|
25 import org.restlet.representation.StringRepresentation;
|
|
26 import org.restlet.resource.Get;
|
|
27 import org.restlet.resource.Options;
|
|
28 import org.restlet.resource.Post;
|
|
29 import org.restlet.resource.ServerResource;
|
|
30 import org.restlet.security.User;
|
|
31
|
2
|
32 import de.mpiwg.itgroup.annotationManager.Constants.NS;
|
0
|
33 import de.mpiwg.itgroup.annotationManager.Errors.TripleStoreSearchError;
|
|
34 import de.mpiwg.itgroup.annotationManager.Errors.TripleStoreStoreError;
|
17
|
35 import de.mpiwg.itgroup.annotationManager.RDFHandling.Annotation;
|
0
|
36 import de.mpiwg.itgroup.annotationManager.RDFHandling.Convert;
|
|
37 import de.mpiwg.itgroup.annotationManager.RDFHandling.RDFSearcher;
|
5
|
38 import de.mpiwg.itgroup.annotationManager.drupal.AnnotationHandler;
|
|
39 import de.mpiwg.itgroup.annotationManager.drupal.UnknowUserException;
|
|
40 import de.mpiwg.itgroup.triplestoremanager.exceptions.TripleStoreHandlerException;
|
|
41
|
0
|
42
|
7
|
43 public class AddAndReadAnnotations extends ServerResource {
|
0
|
44
|
|
45 private Logger logger = Logger.getRootLogger();
|
|
46
|
|
47
|
|
48
|
|
49 @Options
|
|
50 public void doOptions(Representation entity) {
|
|
51 Form responseHeaders = (Form) getResponse().getAttributes().get(
|
|
52 "org.restlet.http.headers");
|
|
53 if (responseHeaders == null) {
|
|
54 responseHeaders = new Form();
|
|
55 getResponse().getAttributes().put("org.restlet.http.headers",
|
|
56 responseHeaders);
|
|
57 }
|
7
|
58 Form requestHeaders = (Form) getRequest().getAttributes().get("org.restlet.http.headers");
|
|
59 String origin = requestHeaders.getFirstValue("Origin", true);
|
|
60 if (origin == null) {
|
|
61 responseHeaders.add("Access-Control-Allow-Origin", "*");
|
|
62 } else {
|
|
63 responseHeaders.add("Access-Control-Allow-Origin", origin);
|
|
64 }
|
|
65 String allowHeaders = requestHeaders.getFirstValue("Access-Control-Request-Headers", true);
|
|
66 if (allowHeaders != null) {
|
|
67 responseHeaders.add("Access-Control-Allow-Headers", allowHeaders);
|
|
68 }
|
0
|
69 responseHeaders.add("Access-Control-Allow-Methods", "POST,OPTIONS,GET");
|
7
|
70 responseHeaders.add("Access-Control-Allow-Credentials", "true");
|
0
|
71 responseHeaders.add("Access-Control-Max-Age", "60");
|
|
72 }
|
|
73
|
2
|
74 @Get("html")
|
|
75 public Representation doGetHTML(Representation entity){
|
|
76
|
|
77 doOptions(entity);
|
|
78 Form form = getRequest().getResourceRef().getQueryAsForm();
|
|
79 String uri = form.getFirstValue("uri");
|
|
80 String user = form.getFirstValue("user");
|
|
81
|
|
82 String limit=form.getFirstValue("limit");
|
|
83 String offset=form.getFirstValue("offset");
|
|
84
|
5
|
85 try {
|
|
86 if (uri!=null){
|
|
87 uri = URLDecoder.decode(uri, "utf-8");
|
|
88 }
|
|
89 } catch (UnsupportedEncodingException e1) {
|
|
90 e1.printStackTrace();
|
|
91 setStatus(Status.CLIENT_ERROR_NOT_ACCEPTABLE);
|
|
92 return null;
|
|
93 }
|
2
|
94
|
|
95 //
|
|
96 RDFSearcher searcher = new RDFSearcher("file:///annotations"); //TODO should ge into config file
|
|
97
|
|
98 String retString="<html><body><table>";
|
3
|
99 String lineFormat="<tr><td><a href=\"%s\">%s</a></td>" +
|
2
|
100 "<td><a href=\"%s\">%s</a></td><td>%s</td><td>%s</td><td><a href=\"%s\">%s</a></td><td><a href=\"%s\">%s</a></td></div>";
|
|
101 try {
|
|
102
|
17
|
103 List<Annotation> annots=searcher.searchByUriUser(uri,user,limit,offset);
|
2
|
104
|
17
|
105 for (Annotation annot:annots){
|
2
|
106
|
|
107
|
|
108 RestServer restServer = (RestServer) getApplication();
|
|
109 String userName=restServer.getUserNameFromLdap(annot.creator);
|
|
110 List<String> xpointer = new ArrayList<String>();
|
|
111
|
|
112 if (annot.xpointers==null || annot.xpointers.size()==0)
|
17
|
113 retString+=String.format(lineFormat, userName,userName,annot.url,annot.url,annot.time,annot.text,annot.xpointer,annot.xpointer,annot.getAnnotationUri(),annot.getAnnotationUri());
|
2
|
114 else {
|
|
115 for(String xpointerString:annot.xpointers){
|
17
|
116 retString+=String.format(lineFormat, userName,userName,annot.url,annot.url,annot.time,annot.text,xpointerString,xpointerString,annot.getAnnotationUri(),annot.getAnnotationUri());
|
2
|
117 }
|
|
118 }
|
|
119
|
|
120 }
|
|
121 } catch (TripleStoreHandlerException e) {
|
|
122 // TODO Auto-generated catch block
|
|
123 e.printStackTrace();
|
|
124 setStatus(Status.SERVER_ERROR_INTERNAL,"TripleStoreHandler Error");
|
|
125 return null;
|
|
126 } catch (TripleStoreSearchError e) {
|
|
127 // TODO Auto-generated catch block
|
|
128 e.printStackTrace();
|
|
129 setStatus(Status.SERVER_ERROR_INTERNAL,"TripleStoreSearch Error");
|
|
130 return null;
|
|
131 }
|
|
132
|
|
133 retString+="</table></body></html>";
|
|
134
|
|
135 logger.debug("sending:");
|
|
136 logger.debug(retString);
|
|
137 return new StringRepresentation(retString,MediaType.TEXT_HTML);
|
|
138 }
|
|
139
|
3
|
140 /**
|
7
|
141 * Erzeugt aus einer Annotation, das f�r den Annotator notwendige JSON-Format
|
3
|
142 * @param annot
|
|
143 * @return
|
|
144 */
|
17
|
145 public JSONObject annot2AnnotatorJSON(Annotation annot){
|
3
|
146 JSONObject jo = new JSONObject();
|
|
147 try {
|
|
148 jo.put("text", annot.text);
|
|
149 jo.put("uri",annot.url);
|
|
150
|
|
151 JSONObject userObject= new JSONObject();
|
|
152 userObject.put("id",annot.creator);
|
|
153
|
|
154 RestServer restServer = (RestServer) getApplication();
|
|
155
|
|
156 String userID= annot.creator;
|
26
|
157 if (userID.startsWith(NS.MPIWG_PERSONS_URL)){
|
|
158 userID=userID.replace(NS.MPIWG_PERSONS_URL, ""); //entferne NAMESPACE
|
3
|
159 }
|
|
160 String userName=restServer.getUserNameFromLdap(userID);
|
|
161 userObject.put("name",userName);
|
|
162
|
|
163 jo.put("user",userObject);
|
|
164
|
|
165 List<String> xpointer = new ArrayList<String>();
|
|
166
|
|
167 if (annot.xpointers==null || annot.xpointers.size()==0)
|
|
168 xpointer.add(annot.xpointer);
|
|
169 else {
|
|
170 for(String xpointerString:annot.xpointers){
|
|
171 xpointer.add(xpointerString);
|
|
172 }
|
|
173 }
|
|
174 jo.put("ranges", transformToRanges(xpointer));
|
17
|
175 jo.put("id", annot.getAnnotationUri());
|
3
|
176 return jo;
|
|
177 } catch (JSONException e) {
|
|
178 // TODO Auto-generated catch block
|
|
179 e.printStackTrace();
|
|
180 return null;
|
|
181 }
|
|
182 }
|
2
|
183
|
0
|
184 @Get("json")
|
2
|
185 public Representation doGetJSON(Representation entity){
|
0
|
186
|
|
187 doOptions(entity);
|
7
|
188 //TODO: Annotator read request does not use parameters
|
0
|
189 Form form = getRequest().getResourceRef().getQueryAsForm();
|
|
190 String uri = form.getFirstValue("uri");
|
|
191 String user = form.getFirstValue("user");
|
|
192
|
|
193 String limit=form.getFirstValue("limit");
|
|
194 String offset=form.getFirstValue("offset");
|
|
195
|
|
196
|
|
197 //
|
|
198 RDFSearcher searcher = new RDFSearcher("file:///annotations"); //TODO should ge into config file
|
|
199
|
|
200 JSONArray ja;
|
|
201 try {
|
|
202
|
17
|
203 List<Annotation> annots=searcher.searchByUriUser(uri,user,limit,offset);
|
0
|
204
|
|
205 ja = new JSONArray();
|
17
|
206 for (Annotation annot:annots){
|
3
|
207 // JSONObject jo = new JSONObject();
|
|
208 // jo.put("text", annot.text);
|
|
209 // jo.put("uri",annot.url);
|
|
210 //
|
|
211 // JSONObject userObject= new JSONObject();
|
|
212 // userObject.put("id",annot.creator);
|
|
213 //
|
|
214 // RestServer restServer = (RestServer) getApplication();
|
|
215 //
|
|
216 // String userID= annot.creator;
|
|
217 // if (userID.startsWith(NS.MPIWG_PERSONS)){
|
|
218 // userID=userID.replace(NS.MPIWG_PERSONS, ""); //entferne NAMESPACE
|
|
219 // }
|
|
220 // String userName=restServer.getUserNameFromLdap(userID);
|
|
221 // userObject.put("name",userName);
|
|
222 //
|
|
223 // jo.put("user",userObject);
|
|
224 //
|
|
225 // List<String> xpointer = new ArrayList<String>();
|
|
226 //
|
|
227 // if (annot.xpointers==null || annot.xpointers.size()==0)
|
|
228 // xpointer.add(annot.xpointer);
|
|
229 // else {
|
|
230 // for(String xpointerString:annot.xpointers){
|
|
231 // xpointer.add(xpointerString);
|
|
232 // }
|
|
233 // }
|
|
234 // jo.put("ranges", transformToRanges(xpointer));
|
|
235 JSONObject jo = annot2AnnotatorJSON(annot);
|
|
236 if (jo!=null){
|
|
237 ja.put(annot2AnnotatorJSON(annot));
|
|
238 } else {
|
|
239 setStatus(Status.SERVER_ERROR_INTERNAL,"JSon Error");
|
|
240 return null;
|
2
|
241 }
|
0
|
242 }
|
|
243 } catch (TripleStoreHandlerException e) {
|
|
244 // TODO Auto-generated catch block
|
|
245 e.printStackTrace();
|
|
246 setStatus(Status.SERVER_ERROR_INTERNAL,"TripleStoreHandler Error");
|
|
247 return null;
|
|
248 } catch (TripleStoreSearchError e) {
|
|
249 // TODO Auto-generated catch block
|
|
250 e.printStackTrace();
|
|
251 setStatus(Status.SERVER_ERROR_INTERNAL,"TripleStoreSearch Error");
|
|
252 return null;
|
3
|
253 }
|
0
|
254
|
7
|
255 // annotator read request returns a list of annotation objects
|
0
|
256 logger.debug("sending:");
|
7
|
257 logger.debug(ja);
|
|
258 return new JsonRepresentation(ja);
|
0
|
259 }
|
|
260
|
|
261 private JSONArray transformToRanges(List<String> xpointers) {
|
|
262
|
|
263 JSONArray ja = new JSONArray();
|
|
264
|
|
265 Pattern rg = Pattern.compile("#xpointer\\(start-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)/range-to\\(end-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)\\)\\)");
|
|
266 Pattern rg1 = Pattern.compile("#xpointer\\(start-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)\\)");
|
|
267
|
|
268
|
|
269
|
|
270 try {
|
|
271 for(String xpointer:xpointers){
|
|
272 String decoded =URLDecoder.decode(xpointer,"utf-8");
|
|
273 Matcher m=rg.matcher(decoded);
|
1
|
274
|
|
275 if (m.find()){
|
0
|
276 {
|
|
277 JSONObject jo = new JSONObject();
|
|
278 jo.put("start", m.group(1));
|
|
279 jo.put("startOffset", m.group(2));
|
|
280 jo.put("end", m.group(3));
|
|
281 jo.put("endOffset", m.group(4));
|
|
282 ja.put(jo);
|
1
|
283 }
|
0
|
284 }
|
|
285 m=rg1.matcher(xpointer);
|
1
|
286 if (m.find()){
|
0
|
287 JSONObject jo = new JSONObject();
|
|
288 jo.put("start", m.group(1));
|
|
289 jo.put("startOffset", m.group(2));
|
|
290
|
|
291 ja.put(jo);
|
|
292 }
|
|
293
|
|
294
|
|
295 }
|
|
296 } catch (JSONException e) {
|
|
297 // TODO Auto-generated catch block
|
|
298 e.printStackTrace();
|
|
299 } catch (UnsupportedEncodingException e) {
|
|
300 // TODO Auto-generated catch block
|
|
301 e.printStackTrace();
|
|
302 }
|
|
303
|
|
304
|
|
305 return ja;
|
|
306
|
|
307
|
|
308
|
|
309
|
|
310
|
|
311 }
|
|
312
|
3
|
313
|
|
314 /**
|
|
315 *
|
|
316 * json hash: username: name des users xpointer: xpointer auf den Ausschnitt
|
|
317 * (incl. der URL des Dokumentes) text: text der annotation annoturl: url
|
|
318 * auf eine Annotation falls extern
|
|
319 *
|
|
320 * @return
|
|
321 */
|
|
322
|
0
|
323 @Post("json")
|
|
324 public Representation doPostJson(Representation entity) {
|
|
325
|
3
|
326 Annotation retVal = doPost(entity);
|
|
327
|
|
328
|
|
329 // JSONObject jo;
|
|
330 // try {
|
|
331 // jo = new JSONObject("{\"annotUrl\":\"" + retVal + "\"}");
|
|
332 // } catch (JSONException e) {
|
|
333 // setStatus(Status.SERVER_ERROR_INTERNAL);
|
|
334 // return null;
|
|
335 // }
|
|
336
|
|
337 if (retVal==null)
|
0
|
338 return null;
|
3
|
339 JSONObject jo = annot2AnnotatorJSON(retVal);
|
0
|
340 JsonRepresentation retRep = new JsonRepresentation(jo);
|
|
341 return retRep;
|
|
342 }
|
|
343
|
|
344 @Post("html")
|
|
345 public Representation doPostHtml(Representation entity) {
|
3
|
346 Annotation retValAnnot = doPost(entity);
|
5
|
347 if (retValAnnot == null) {
|
|
348 return null;
|
|
349 }
|
|
350
|
|
351
|
17
|
352 String retVal=retValAnnot.getAnnotationUri();
|
0
|
353 if (retVal == null) {
|
|
354 return null;
|
|
355 }
|
5
|
356
|
0
|
357 String text = String.format(
|
|
358 "<html><body><a href=\"%s\">%s</a></body></html>", retVal
|
|
359 .replace(">", "").replace("<", ""),
|
|
360 retVal.replace(">", ">").replace("<", "<"));
|
|
361 Representation retRep = new StringRepresentation(text,
|
|
362 MediaType.TEXT_HTML);
|
|
363 return retRep;
|
|
364 }
|
|
365
|
17
|
366 public Annotation doPost(Representation entity) {
|
3
|
367
|
|
368 doOptions(entity);
|
17
|
369 Annotation annot;
|
0
|
370 // versuche basic authentifizierung und hole den Benutzer von dort.
|
|
371
|
|
372 // User authUser;= handleBasicAuthentification(entity);
|
|
373
|
|
374 if (entity.getMediaType().equals(MediaType.APPLICATION_JSON)) {
|
|
375
|
|
376 JsonRepresentation jrep;
|
|
377 try {
|
|
378 jrep = new JsonRepresentation(entity);
|
|
379 } catch (IOException e1) {
|
|
380 setStatus(Status.SERVER_ERROR_INTERNAL);
|
|
381 return null;
|
|
382 }
|
|
383
|
|
384 // try {
|
|
385 // logger.debug(jrep.getText());
|
|
386 // } catch (IOException e1) {
|
|
387 // // TODO Auto-generated catch block
|
|
388 // e1.printStackTrace();
|
|
389 // }
|
|
390 //
|
|
391
|
|
392 try {
|
|
393 JSONObject jo = jrep.getJsonObject();
|
4
|
394 if(jo==null){
|
|
395 setStatus(Status.SERVER_ERROR_INTERNAL);
|
|
396 return null;
|
|
397 }
|
|
398
|
|
399 String mode=null;
|
|
400 if(jo.has("mode")){
|
|
401 mode = jo.getString("mode"); // hole modus
|
|
402 }
|
0
|
403 if (mode==null || mode.equals(""))
|
|
404 mode="annotea"; // default mode (annotea) TODO make this configurable
|
|
405
|
|
406 if (mode.equals("annotator") ) { // annotator format
|
|
407 annot = handleAnnotatorSchema(jo, entity);
|
|
408 logger.debug("storing annotator object");
|
|
409 logger.debug(jo);
|
|
410 } else if (mode.equals("annotea")){
|
|
411 annot = handleAnnotea(jo, entity);
|
|
412 } else {
|
|
413 setStatus(Status.CLIENT_ERROR_BAD_REQUEST,"mode "+mode+"not supported!");
|
|
414 return null;
|
|
415 }
|
|
416
|
|
417 } catch (JSONException e) {
|
|
418 setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
|
|
419 return null;
|
|
420 }
|
|
421
|
|
422 } else if (entity.getMediaType().equals(MediaType.APPLICATION_WWW_FORM)) {
|
|
423 annot = handleForm(entity);
|
|
424
|
|
425 } else {
|
|
426 setStatus(Status.CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE);
|
|
427
|
|
428 return null;
|
|
429 }
|
|
430
|
|
431 if (annot==null){
|
|
432 return null;
|
|
433 }
|
|
434 if (annot.xpointer == null || annot.creator == null) {
|
|
435 setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
|
|
436
|
|
437 return null;
|
|
438 }
|
|
439
|
|
440
|
|
441
|
|
442 try {
|
|
443 return new Convert("file:///annotations").storeAnnotation(annot);
|
|
444 } catch (TripleStoreStoreError e) {
|
|
445 e.printStackTrace();
|
|
446 setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStore Error");
|
|
447 return null;
|
|
448 }
|
|
449 }
|
|
450
|
2
|
451
|
|
452 /**
|
|
453 *
|
|
454 * @param entity should contain a form with the parameters "username", "password", "xpointer","text","uri","type"
|
|
455 *
|
|
456 * username,password is optional, if not given BasicAuthentification is used.
|
|
457 *
|
|
458 *
|
|
459 *
|
|
460 * If username given as a URI, the username will be transformed to an URI, username will be added to the MPIWG namespace defined in de.mpiwg.itgroup.annotationManager.Constants.NS
|
|
461 *
|
|
462 * @return
|
|
463 */
|
17
|
464 protected Annotation handleForm(Representation entity) {
|
|
465 Annotation annot;
|
0
|
466 Form form = new Form(entity);
|
|
467 String username = form.getValues("username");
|
5
|
468 String mode = form.getValues("mode");
|
0
|
469 String password = form.getValues("password");
|
|
470 String xpointer = form.getValues("xpointer");
|
|
471 String text = form.getValues("text");
|
5
|
472 String title = form.getValues("title");
|
0
|
473 String url = form.getValues("url");
|
|
474 String type = form.getValues("type");
|
|
475 RestServer restServer = (RestServer) getApplication();
|
|
476
|
|
477 // falls user and password nicht null sind:
|
|
478 User userFromForm = null;
|
|
479 if (username != null && password != null) {
|
|
480 if (restServer.authenticate(username, password, getRequest())) {
|
|
481 userFromForm = new User(username);
|
|
482 }
|
|
483 }
|
|
484 User authUser = null;
|
|
485
|
|
486 if (userFromForm == null) {
|
|
487 authUser = handleBasicAuthentification(entity);
|
|
488 }
|
|
489
|
|
490 // weder BasicAuth noch FormAuth
|
|
491 if (authUser == null && userFromForm == null) {
|
|
492 setStatus(Status.CLIENT_ERROR_FORBIDDEN);
|
|
493 return null;
|
|
494 }
|
|
495
|
|
496 if (userFromForm != null) {
|
|
497 username = userFromForm.getIdentifier();
|
|
498 } else {
|
|
499 username = authUser.getIdentifier();
|
|
500 }
|
|
501
|
2
|
502 //username should be a URI, if not it will set to the MPIWG namespace defined in de.mpiwg.itgroup.annotationManager.Constants.NS
|
5
|
503 String usernameOrig=username;
|
2
|
504 if (!username.startsWith("http"))
|
26
|
505 username=NS.MPIWG_PERSONS_URL+username;
|
2
|
506
|
5
|
507 if (mode.equals("complexAnnotation")){// Annotation mit text in externer ressource
|
|
508
|
|
509 Context context = getContext();
|
|
510 String drupalPath = context.getParameters().getFirstValue("de.mpiwg.itgroup.annotationManager.drupalServer");
|
|
511
|
|
512
|
|
513 AnnotationHandler ah = new AnnotationHandler(drupalPath);
|
|
514 JSONObject newAnnot;
|
|
515 try {
|
|
516 newAnnot = ah.createAnnotation(title, text, usernameOrig, password);
|
|
517 } catch (UnknowUserException e1) {
|
|
518 setStatus(Status.CLIENT_ERROR_FORBIDDEN);
|
|
519 e1.printStackTrace();
|
|
520 return null;
|
|
521 }
|
|
522 try {
|
17
|
523 annot= new Annotation(xpointer, username, null, text, type, newAnnot.getString("node_uri"));
|
5
|
524 } catch (JSONException e) {
|
|
525 // TODO Auto-generated catch block
|
|
526 e.printStackTrace();
|
|
527 setStatus(Status.SERVER_ERROR_INTERNAL);
|
|
528 return null;
|
|
529 }
|
|
530 } else
|
17
|
531 annot = new Annotation(xpointer, username, null, text,
|
0
|
532 type, url);
|
|
533 return annot;
|
|
534 }
|
|
535
|
|
536 @Post
|
|
537 public Representation doPostHtml2(Representation entity) {
|
|
538 return doPostHtml(entity);
|
|
539 }
|
|
540
|
|
541 private User handleBasicAuthentification(Representation entity) {
|
|
542 RestServer restServer = (RestServer) getApplication();
|
|
543 if (!restServer.authenticate(getRequest(), getResponse())) {
|
|
544 // Not authenticated
|
|
545 return null;
|
|
546 }
|
|
547
|
|
548 ClientInfo ci = getRequest().getClientInfo();
|
|
549 logger.debug(ci);
|
|
550 return getRequest().getClientInfo().getUser();
|
|
551
|
|
552 }
|
|
553
|
|
554 /**
|
|
555 * using a minimal annotation format based on the annotea specification
|
|
556 *
|
|
557 * @param jo
|
|
558 * must contain xpointer, text,url,type and can contain a
|
|
559 * username, if not the username form the authentification will
|
|
560 * be used.
|
|
561 * @param authUser
|
|
562 * user object
|
2
|
563 * The username will be transformed to an URI if not given already as URI, if not it will set to the MPIWG namespace defined in de.mpiwg.itgroup.annotationManager.Constants.NS
|
|
564
|
0
|
565 * @return
|
|
566 * @throws JSONException
|
|
567 */
|
|
568 public Annotation handleAnnotea(JSONObject jo, Representation entity)
|
|
569 throws JSONException {
|
|
570
|
|
571 User authUser = handleBasicAuthentification(entity);
|
|
572 String username = jo.getString("username"); // not required, if no
|
|
573 // username given authuser
|
|
574 // will be used.
|
|
575 String xpointer = jo.getString("xpointer");
|
|
576 String text = null;
|
|
577 if (jo.has("text"))
|
|
578 text = jo.getString("text");
|
|
579
|
|
580 String url = null;
|
|
581 if (jo.has("url"))
|
|
582 url = jo.getString("url");
|
|
583
|
|
584 String type = null;
|
|
585 if (jo.has("type"))
|
|
586 type = jo.getString("type");
|
|
587
|
|
588 if (username == null)
|
|
589 username = authUser.getIdentifier();
|
|
590
|
2
|
591 //username should be a URI, if not it will set to the MPIWG namespace defined in de.mpiwg.itgroup.annotationManager.Constants.NS
|
|
592 if (!username.startsWith("http"))
|
26
|
593 username=NS.MPIWG_PERSONS_URL+username;
|
2
|
594
|
17
|
595 return new Annotation(xpointer, username, null, text, type, url);
|
0
|
596 }
|
|
597
|
|
598 /**
|
|
599 * uses the specification from the annotator project.
|
|
600 *
|
3
|
601 * @see{https://github.com/okfn/annotator/wiki/Annotation-format} The user
|
0
|
602 * object must
|
|
603 * contain an
|
|
604 * id and
|
|
605 * password or
|
|
606 * basic
|
|
607 * authentification
|
|
608 * is used.
|
2
|
609 * The username will be transformed to an URI if not given already as URI, if not it will set to the MPIWG namespace defined in de.mpiwg.itgroup.annotationManager.Constants.NS
|
0
|
610 * @param jo
|
|
611 * @param authUser
|
|
612 * @return
|
|
613 * @throws JSONException
|
|
614 */
|
17
|
615 public Annotation handleAnnotatorSchema(JSONObject jo,
|
0
|
616 Representation entity) throws JSONException {
|
17
|
617 Annotation annot;
|
0
|
618 String url = jo.getString("uri");
|
|
619 String text = jo.getString("text");
|
|
620
|
|
621 String username = null;
|
|
622 if (jo.has("user")) { // not required, if no username given authuser
|
|
623 // will be used otherwise username and password
|
|
624 // has to be submitted
|
|
625 JSONObject user = jo.getJSONObject("user");
|
|
626 if (user.has("id")) {
|
|
627 username = user.getString("id");
|
|
628 if(!user.has("password")){
|
|
629 User authUser = handleBasicAuthentification(entity);
|
|
630 if (authUser==null){
|
|
631 setStatus(Status.CLIENT_ERROR_FORBIDDEN);
|
|
632 return null;
|
|
633 }
|
|
634 username = authUser.getIdentifier();
|
|
635 } else {
|
|
636 String password = user.getString("password");
|
|
637 if (!((RestServer) getApplication()).authenticate(username,
|
|
638 password, getRequest())) {
|
|
639 setStatus(Status.CLIENT_ERROR_FORBIDDEN);
|
|
640 return null;
|
|
641 }
|
|
642 }
|
|
643 }
|
|
644
|
|
645 } else {
|
|
646 User authUser = handleBasicAuthentification(entity);
|
|
647 if (authUser == null) {
|
|
648 setStatus(Status.CLIENT_ERROR_FORBIDDEN);
|
|
649 return null;
|
|
650 }
|
|
651 username = authUser.getIdentifier();
|
|
652 }
|
|
653
|
|
654 String xpointer;
|
|
655 if (jo.has("ranges")) {
|
|
656 JSONObject ranges = jo.getJSONArray("ranges").getJSONObject(0);
|
|
657 String start = ranges.getString("start");
|
|
658 String end = ranges.getString("end");
|
|
659 String startOffset = ranges.getString("startOffset");
|
|
660 String endOffset = ranges.getString("endOffset");
|
|
661
|
|
662 try {
|
|
663 xpointer = url+"#"+
|
|
664 URLEncoder.encode(String.format(
|
|
665 "xpointer(start-point(string-range(\"%s\",%s,1))/range-to(end-point(string-range(\"%s\",%s,1))))",
|
|
666 start, startOffset, end, endOffset),"utf-8");
|
|
667 } catch (UnsupportedEncodingException e) {
|
|
668 e.printStackTrace();
|
|
669 setStatus(Status.SERVER_ERROR_INTERNAL);
|
|
670 return null;
|
|
671 }
|
|
672 } else {
|
|
673 xpointer = url;
|
|
674 }
|
2
|
675
|
|
676 //username should be a URI, if not it will set to the MPIWG namespace defined in de.mpiwg.itgroup.annotationManager.Constants.NS
|
|
677 if (!username.startsWith("http"))
|
26
|
678 username=NS.MPIWG_PERSONS_URL+username;
|
2
|
679
|
17
|
680 return new Annotation(xpointer, username, null, text, null);
|
0
|
681 }
|
|
682
|
|
683 }
|