Mercurial > hg > AnnotationManagerN4J
annotate src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java @ 18:aafa3884b2c4
new AnnotationStore restlet for HTML-UI.
reorganisation of classes.
author | casties |
---|---|
date | Wed, 05 Sep 2012 18:05:54 +0200 |
parents | 794077e6288c |
children | f0f55ab768c9 |
rev | line source |
---|---|
3 | 1 /** |
2 * Base class for Annotator resource classes. | |
3 */ | |
4 package de.mpiwg.itgroup.annotations.restlet; | |
5 | |
6 import java.io.UnsupportedEncodingException; | |
7 import java.security.InvalidKeyException; | |
8 import java.security.SignatureException; | |
5 | 9 import java.text.SimpleDateFormat; |
3 | 10 import java.util.ArrayList; |
5 | 11 import java.util.Calendar; |
16 | 12 import java.util.HashSet; |
3 | 13 import java.util.List; |
16 | 14 import java.util.Set; |
3 | 15 import java.util.regex.Matcher; |
16 import java.util.regex.Pattern; | |
17 | |
4 | 18 import javax.servlet.ServletContext; |
19 | |
3 | 20 import net.oauth.jsontoken.Checker; |
21 import net.oauth.jsontoken.JsonToken; | |
22 import net.oauth.jsontoken.JsonTokenParser; | |
23 import net.oauth.jsontoken.SystemClock; | |
24 import net.oauth.jsontoken.crypto.HmacSHA256Verifier; | |
25 import net.oauth.jsontoken.crypto.Verifier; | |
26 | |
27 import org.apache.commons.codec.binary.Base64; | |
28 import org.apache.log4j.Logger; | |
29 import org.json.JSONArray; | |
30 import org.json.JSONException; | |
31 import org.json.JSONObject; | |
32 import org.restlet.data.Form; | |
33 import org.restlet.data.Status; | |
34 import org.restlet.representation.Representation; | |
35 import org.restlet.resource.Options; | |
36 import org.restlet.resource.ServerResource; | |
37 | |
9 | 38 import de.mpiwg.itgroup.annotations.Actor; |
4 | 39 import de.mpiwg.itgroup.annotations.Annotation; |
18 | 40 import de.mpiwg.itgroup.annotations.NS; |
4 | 41 import de.mpiwg.itgroup.annotations.Annotation.FragmentTypes; |
10 | 42 import de.mpiwg.itgroup.annotations.Group; |
43 import de.mpiwg.itgroup.annotations.Person; | |
4 | 44 import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore; |
3 | 45 |
46 /** | |
47 * Base class for Annotator resource classes. | |
48 * | |
49 * @author dwinter, casties | |
50 * | |
51 */ | |
52 public abstract class AnnotatorResourceImpl extends ServerResource { | |
53 | |
4 | 54 protected static Logger logger = Logger.getLogger(AnnotatorResourceImpl.class); |
55 | |
56 private AnnotationStore store; | |
3 | 57 |
58 protected String getAllowedMethodsForHeader() { | |
59 return "OPTIONS,GET,POST"; | |
60 } | |
61 | |
4 | 62 protected AnnotationStore getAnnotationStore() { |
63 if (store == null) { | |
64 ServletContext sc = (ServletContext) getContext().getServerDispatcher().getContext().getAttributes() | |
65 .get("org.restlet.ext.servlet.ServletContext"); | |
66 logger.debug("Getting AnnotationStore from Context"); | |
18 | 67 store = (AnnotationStore) sc.getAttribute(BaseRestlet.ANNSTORE_KEY); |
4 | 68 } |
69 return store; | |
70 } | |
71 | |
3 | 72 public String encodeJsonId(String id) { |
73 try { | |
74 return Base64.encodeBase64URLSafeString(id.getBytes("UTF-8")); | |
75 } catch (UnsupportedEncodingException e) { | |
76 return null; | |
77 } | |
78 } | |
79 | |
80 public String decodeJsonId(String id) { | |
81 try { | |
82 return new String(Base64.decodeBase64(id), "UTF-8"); | |
83 } catch (UnsupportedEncodingException e) { | |
84 return null; | |
85 } | |
86 } | |
87 | |
88 /** | |
89 * Handle options request to allow CORS for AJAX. | |
90 * | |
91 * @param entity | |
92 */ | |
93 @Options | |
94 public void doOptions(Representation entity) { | |
95 logger.debug("AnnotatorResourceImpl doOptions!"); | |
96 setCorsHeaders(); | |
97 } | |
98 | |
99 /** | |
100 * set headers to allow CORS for AJAX. | |
101 */ | |
102 protected void setCorsHeaders() { | |
103 Form responseHeaders = (Form) getResponse().getAttributes().get("org.restlet.http.headers"); | |
104 if (responseHeaders == null) { | |
105 responseHeaders = new Form(); | |
106 getResponse().getAttributes().put("org.restlet.http.headers", responseHeaders); | |
107 } | |
108 responseHeaders.add("Access-Control-Allow-Methods", getAllowedMethodsForHeader()); | |
109 // echo back Origin and Request-Headers | |
110 Form requestHeaders = (Form) getRequest().getAttributes().get("org.restlet.http.headers"); | |
111 String origin = requestHeaders.getFirstValue("Origin", true); | |
112 if (origin == null) { | |
113 responseHeaders.add("Access-Control-Allow-Origin", "*"); | |
114 } else { | |
115 responseHeaders.add("Access-Control-Allow-Origin", origin); | |
116 } | |
117 String allowHeaders = requestHeaders.getFirstValue("Access-Control-Request-Headers", true); | |
118 if (allowHeaders != null) { | |
119 responseHeaders.add("Access-Control-Allow-Headers", allowHeaders); | |
120 } | |
121 responseHeaders.add("Access-Control-Allow-Credentials", "true"); | |
122 responseHeaders.add("Access-Control-Max-Age", "60"); | |
123 } | |
124 | |
125 /** | |
126 * returns if authentication information from headers is valid. | |
127 * | |
128 * @param entity | |
129 * @return | |
130 */ | |
131 public boolean isAuthenticated(Representation entity) { | |
132 return (checkAuthToken(entity) != null); | |
133 } | |
134 | |
135 /** | |
4 | 136 * checks Annotator Auth plugin authentication information from headers. |
137 * returns userId if successful. | |
3 | 138 * |
139 * @param entity | |
140 * @return | |
141 */ | |
142 public String checkAuthToken(Representation entity) { | |
143 Form requestHeaders = (Form) getRequest().getAttributes().get("org.restlet.http.headers"); | |
144 String authToken = requestHeaders.getFirstValue("x-annotator-auth-token", true); | |
14
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
145 if (authToken == null) return null; |
3 | 146 // decode token first to get consumer key |
147 JsonToken token = new JsonTokenParser(null, null).deserialize(authToken); | |
148 String userId = token.getParamAsPrimitive("userId").getAsString(); | |
149 String consumerKey = token.getParamAsPrimitive("consumerKey").getAsString(); | |
150 // get stored consumer secret for key | |
18 | 151 BaseRestlet restServer = (BaseRestlet) getApplication(); |
3 | 152 String consumerSecret = restServer.getConsumerSecret(consumerKey); |
153 logger.debug("requested consumer key=" + consumerKey + " secret=" + consumerSecret); | |
154 if (consumerSecret == null) { | |
155 return null; | |
156 } | |
157 // logger.debug(String.format("token=%s tokenString=%s signatureAlgorithm=%s",token,token.getTokenString(),token.getSignatureAlgorithm())); | |
158 try { | |
159 List<Verifier> verifiers = new ArrayList<Verifier>(); | |
160 // we only do HS256 yet | |
161 verifiers.add(new HmacSHA256Verifier(consumerSecret.getBytes("UTF-8"))); | |
162 // verify token signature(should really be static...) | |
163 new JsonTokenParser(new SystemClock(), null, (Checker[]) null).verify(token, verifiers); | |
164 } catch (SignatureException e) { | |
165 // TODO Auto-generated catch block | |
166 e.printStackTrace(); | |
167 } catch (InvalidKeyException e) { | |
168 // TODO Auto-generated catch block | |
169 e.printStackTrace(); | |
170 } catch (UnsupportedEncodingException e) { | |
171 // TODO Auto-generated catch block | |
172 e.printStackTrace(); | |
173 } | |
174 // must be ok then | |
175 logger.debug("auth OK! user=" + userId); | |
176 return userId; | |
177 } | |
178 | |
179 /** | |
180 * creates Annotator-JSON from an Annotation object. | |
181 * | |
182 * @param annot | |
14
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
183 * @param forAnonymous TODO |
3 | 184 * @return |
185 */ | |
14
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
186 public JSONObject createAnnotatorJson(Annotation annot, boolean forAnonymous) { |
5 | 187 // return user as a JSON object (otherwise just as string) |
3 | 188 boolean makeUserObject = true; |
189 JSONObject jo = new JSONObject(); | |
190 try { | |
4 | 191 jo.put("text", annot.getBodyText()); |
192 jo.put("uri", annot.getTargetBaseUri()); | |
3 | 193 |
16 | 194 /* |
195 * user | |
196 */ | |
3 | 197 if (makeUserObject) { |
198 // create user object | |
199 JSONObject userObject = new JSONObject(); | |
10 | 200 Actor creator = annot.getCreator(); |
3 | 201 // save creator as uri |
10 | 202 userObject.put("uri", creator.getUri()); |
3 | 203 // make short user id |
10 | 204 String userId = creator.getIdString(); |
9 | 205 // set as id |
4 | 206 userObject.put("id", userId); |
3 | 207 // get full name |
10 | 208 String userName = creator.getName(); |
5 | 209 if (userName == null) { |
18 | 210 BaseRestlet restServer = (BaseRestlet) getApplication(); |
5 | 211 userName = restServer.getFullNameFromLdap(userId); |
212 } | |
3 | 213 userObject.put("name", userName); |
214 // save user object | |
215 jo.put("user", userObject); | |
216 } else { | |
217 // save user as string | |
4 | 218 jo.put("user", annot.getCreatorUri()); |
3 | 219 } |
220 | |
16 | 221 /* |
222 * ranges | |
223 */ | |
4 | 224 if (annot.getTargetFragment() != null) { |
3 | 225 // we only look at the first xpointer |
4 | 226 List<String> fragments = new ArrayList<String>(); |
227 fragments.add(annot.getTargetFragment()); | |
228 FragmentTypes xt = annot.getFragmentType(); | |
229 if (xt == FragmentTypes.XPOINTER) { | |
230 jo.put("ranges", transformToRanges(fragments)); | |
231 } else if (xt == FragmentTypes.AREA) { | |
232 jo.put("areas", transformToAreas(fragments)); | |
3 | 233 } |
234 } | |
10 | 235 |
16 | 236 /* |
237 * permissions | |
238 */ | |
10 | 239 JSONObject perms = new JSONObject(); |
240 jo.put("permissions", perms); | |
241 // admin | |
242 JSONArray adminPerms = new JSONArray(); | |
243 perms.put("admin", adminPerms); | |
244 Actor adminPerm = annot.getAdminPermission(); | |
245 if (adminPerm != null) { | |
246 adminPerms.put(adminPerm.getIdString()); | |
14
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
247 } else if (forAnonymous) { |
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
248 // set something because its not allowed for anonymous |
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
249 adminPerms.put("not-you"); |
10 | 250 } |
251 // delete | |
252 JSONArray deletePerms = new JSONArray(); | |
253 perms.put("delete", deletePerms); | |
254 Actor deletePerm = annot.getDeletePermission(); | |
255 if (deletePerm != null) { | |
256 deletePerms.put(deletePerm.getIdString()); | |
14
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
257 } else if (forAnonymous) { |
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
258 // set something because its not allowed for anonymous |
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
259 deletePerms.put("not-you"); |
10 | 260 } |
261 // update | |
262 JSONArray updatePerms = new JSONArray(); | |
263 perms.put("update", updatePerms); | |
264 Actor updatePerm = annot.getUpdatePermission(); | |
265 if (updatePerm != null) { | |
266 updatePerms.put(updatePerm.getIdString()); | |
14
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
267 } else if (forAnonymous) { |
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
268 // set something because its not allowed for anonymous |
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
269 updatePerms.put("not-you"); |
10 | 270 } |
271 // read | |
272 JSONArray readPerms = new JSONArray(); | |
273 perms.put("read", readPerms); | |
274 Actor readPerm = annot.getReadPermission(); | |
275 if (readPerm != null) { | |
276 readPerms.put(readPerm.getIdString()); | |
277 } | |
278 | |
16 | 279 /* |
280 * tags | |
281 */ | |
282 Set<String> tagset = annot.getTags(); | |
283 if (tagset != null) { | |
284 JSONArray tags = new JSONArray(); | |
285 jo.put("tags", tags); | |
286 for (String tag : tagset) { | |
287 tags.put(tag); | |
288 } | |
289 } | |
290 | |
291 /* | |
292 * id | |
293 */ | |
3 | 294 // encode Annotation URL (=id) in base64 |
4 | 295 String annotUrl = annot.getUri(); |
3 | 296 String annotId = encodeJsonId(annotUrl); |
297 jo.put("id", annotId); | |
298 return jo; | |
299 } catch (JSONException e) { | |
300 // TODO Auto-generated catch block | |
301 e.printStackTrace(); | |
302 } | |
303 return null; | |
304 } | |
305 | |
306 private JSONArray transformToRanges(List<String> xpointers) { | |
307 | |
308 JSONArray ja = new JSONArray(); | |
309 | |
310 Pattern rg = Pattern | |
4 | 311 .compile("xpointer\\(start-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)/range-to\\(end-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)\\)\\)"); |
312 Pattern rg1 = Pattern.compile("xpointer\\(start-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)\\)"); | |
3 | 313 |
314 try { | |
315 for (String xpointer : xpointers) { | |
10 | 316 // String decoded = URLDecoder.decode(xpointer, "utf-8"); |
5 | 317 String decoded = xpointer; |
3 | 318 Matcher m = rg.matcher(decoded); |
319 | |
320 if (m.find()) { | |
321 { | |
322 JSONObject jo = new JSONObject(); | |
323 jo.put("start", m.group(1)); | |
324 jo.put("startOffset", m.group(2)); | |
325 jo.put("end", m.group(3)); | |
326 jo.put("endOffset", m.group(4)); | |
327 ja.put(jo); | |
328 } | |
329 } | |
330 m = rg1.matcher(xpointer); | |
331 if (m.find()) { | |
332 JSONObject jo = new JSONObject(); | |
333 jo.put("start", m.group(1)); | |
334 jo.put("startOffset", m.group(2)); | |
335 | |
336 ja.put(jo); | |
337 } | |
338 } | |
339 } catch (JSONException e) { | |
340 // TODO Auto-generated catch block | |
341 e.printStackTrace(); | |
342 } | |
343 return ja; | |
344 } | |
345 | |
346 private JSONArray transformToAreas(List<String> xpointers) { | |
347 | |
348 JSONArray ja = new JSONArray(); | |
349 | |
4 | 350 Pattern rg = Pattern.compile("xywh=(\\w*:)([\\d\\.]+),([\\d\\.]+),([\\d\\.]+),([\\d\\.]+)"); |
3 | 351 |
352 try { | |
353 for (String xpointer : xpointers) { | |
10 | 354 // String decoded = URLDecoder.decode(xpointer, "utf-8"); |
5 | 355 String decoded = xpointer; |
3 | 356 Matcher m = rg.matcher(decoded); |
357 | |
358 if (m.find()) { | |
359 { | |
360 JSONObject jo = new JSONObject(); | |
10 | 361 @SuppressWarnings("unused") |
3 | 362 String unit = m.group(1); |
363 jo.put("x", m.group(2)); | |
364 jo.put("y", m.group(3)); | |
365 jo.put("width", m.group(4)); | |
366 jo.put("height", m.group(5)); | |
367 ja.put(jo); | |
368 } | |
369 } | |
370 } | |
371 } catch (JSONException e) { | |
372 // TODO Auto-generated catch block | |
373 e.printStackTrace(); | |
374 } | |
375 return ja; | |
376 } | |
377 | |
5 | 378 protected String parseArea(JSONObject area) throws JSONException { |
4 | 379 String x = area.getString("x"); |
380 String y = area.getString("y"); | |
381 String width = "0"; | |
382 String height = "0"; | |
383 if (area.has("width")) { | |
384 width = area.getString("width"); | |
385 height = area.getString("height"); | |
386 } | |
5 | 387 String fragment = String.format("xywh=fraction:%s,%s,%s,%s", x, y, width, height); |
4 | 388 return fragment; |
389 } | |
390 | |
5 | 391 protected String parseRange(JSONObject range) throws JSONException { |
4 | 392 String start = range.getString("start"); |
393 String end = range.getString("end"); | |
394 String startOffset = range.getString("startOffset"); | |
395 String endOffset = range.getString("endOffset"); | |
396 | |
5 | 397 String fragment = String.format( |
4 | 398 "xpointer(start-point(string-range(\"%s\",%s,1))/range-to(end-point(string-range(\"%s\",%s,1))))", start, |
5 | 399 startOffset, end, endOffset); |
4 | 400 return fragment; |
401 } | |
402 | |
3 | 403 /** |
5 | 404 * Creates an Annotation object with data from JSON. |
3 | 405 * |
4 | 406 * uses the specification from the annotator project: {@link https |
407 * ://github.com/okfn/annotator/wiki/Annotation-format} | |
3 | 408 * |
4 | 409 * The username will be transformed to an URI if not given already as URI, |
410 * if not it will set to the MPIWG namespace defined in | |
3 | 411 * de.mpiwg.itgroup.annotationManager.Constants.NS |
412 * | |
413 * @param jo | |
414 * @return | |
415 * @throws JSONException | |
4 | 416 * @throws UnsupportedEncodingException |
3 | 417 */ |
4 | 418 public Annotation createAnnotation(JSONObject jo, Representation entity) throws JSONException, UnsupportedEncodingException { |
3 | 419 return updateAnnotation(new Annotation(), jo, entity); |
420 } | |
421 | |
5 | 422 /** |
423 * Updates an Annotation object with data from JSON. | |
424 * | |
425 * uses the specification from the annotator project: {@link https | |
426 * ://github.com/okfn/annotator/wiki/Annotation-format} | |
427 * | |
428 * The username will be transformed to an URI if not given already as URI, | |
429 * if not it will set to the MPIWG namespace defined in | |
430 * de.mpiwg.itgroup.annotationManager.Constants.NS | |
431 * | |
432 * @param annot | |
433 * @param jo | |
434 * @return | |
435 * @throws JSONException | |
436 * @throws UnsupportedEncodingException | |
437 */ | |
4 | 438 public Annotation updateAnnotation(Annotation annot, JSONObject jo, Representation entity) throws JSONException, |
439 UnsupportedEncodingException { | |
16 | 440 /* |
441 * target uri | |
442 */ | |
3 | 443 if (jo.has("uri")) { |
4 | 444 annot.setTargetBaseUri(jo.getString("uri")); |
3 | 445 } |
16 | 446 /* |
447 * annotation text | |
448 */ | |
3 | 449 if (jo.has("text")) { |
4 | 450 annot.setBodyText(jo.getString("text")); |
3 | 451 } |
16 | 452 /* |
453 * check authentication | |
454 */ | |
3 | 455 String authUser = checkAuthToken(entity); |
456 if (authUser == null) { | |
4 | 457 /* |
458 * // try http auth User httpUser = getHttpAuthUser(entity); if | |
459 * (httpUser == null) { | |
460 */ | |
461 setStatus(Status.CLIENT_ERROR_FORBIDDEN); | |
462 return null; | |
463 /* | |
464 * } authUser = httpUser.getIdentifier(); | |
465 */ | |
3 | 466 } |
16 | 467 /* |
468 * get or create creator object | |
469 */ | |
9 | 470 Actor creator = annot.getCreator(); |
471 if (creator == null) { | |
10 | 472 creator = new Person(); |
9 | 473 annot.setCreator(creator); |
474 } | |
3 | 475 // username not required, if no username given authuser will be used |
476 String username = null; | |
10 | 477 String userUri = creator.getUri(); |
3 | 478 if (jo.has("user")) { |
479 if (jo.get("user") instanceof String) { | |
480 // user is just a String | |
481 username = jo.getString("user"); | |
10 | 482 creator.setId(username); |
3 | 483 // TODO: what if username and authUser are different? |
484 } else { | |
485 // user is an object | |
486 JSONObject user = jo.getJSONObject("user"); | |
487 if (user.has("id")) { | |
10 | 488 String id = user.getString("id"); |
489 creator.setId(id); | |
490 username = id; | |
3 | 491 } |
492 if (user.has("uri")) { | |
493 userUri = user.getString("uri"); | |
494 } | |
495 } | |
496 } | |
497 if (username == null) { | |
498 username = authUser; | |
499 } | |
5 | 500 // try to get full name |
9 | 501 if (creator.getName() == null && username != null) { |
18 | 502 BaseRestlet restServer = (BaseRestlet) getApplication(); |
5 | 503 String fullName = restServer.getFullNameFromLdap(username); |
9 | 504 creator.setName(fullName); |
5 | 505 } |
506 // userUri should be a URI, if not it will set to the MPIWG namespace | |
3 | 507 if (userUri == null) { |
508 if (username.startsWith("http")) { | |
509 userUri = username; | |
510 } else { | |
511 userUri = NS.MPIWG_PERSONS_URL + username; | |
512 } | |
513 } | |
514 // TODO: should we overwrite the creator? | |
9 | 515 if (creator.getUri() == null) { |
516 creator.setUri(userUri); | |
5 | 517 } |
16 | 518 /* |
519 * creation date | |
520 */ | |
5 | 521 if (annot.getCreated() == null) { |
522 // set creation date | |
523 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); | |
524 String ct = format.format(Calendar.getInstance().getTime()); | |
525 annot.setCreated(ct); | |
526 } | |
3 | 527 |
16 | 528 /* |
529 * create xpointer from the first range/area | |
530 */ | |
3 | 531 if (jo.has("ranges")) { |
532 JSONObject ranges = jo.getJSONArray("ranges").getJSONObject(0); | |
4 | 533 annot.setFragmentType(FragmentTypes.XPOINTER); |
534 String fragment = parseRange(ranges); | |
535 annot.setTargetFragment(fragment); | |
3 | 536 } |
537 if (jo.has("areas")) { | |
538 JSONObject area = jo.getJSONArray("areas").getJSONObject(0); | |
4 | 539 annot.setFragmentType(FragmentTypes.AREA); |
540 String fragment = parseArea(area); | |
541 annot.setTargetFragment(fragment); | |
3 | 542 } |
10 | 543 |
16 | 544 /* |
545 * permissions | |
546 */ | |
10 | 547 if (jo.has("permissions")) { |
548 JSONObject permissions = jo.getJSONObject("permissions"); | |
549 if (permissions.has("admin")) { | |
550 JSONArray perms = permissions.getJSONArray("admin"); | |
551 Actor actor = getActorFromPermissions(perms); | |
552 annot.setAdminPermission(actor); | |
553 } | |
554 if (permissions.has("delete")) { | |
555 JSONArray perms = permissions.getJSONArray("delete"); | |
556 Actor actor = getActorFromPermissions(perms); | |
557 annot.setDeletePermission(actor); | |
558 } | |
559 if (permissions.has("update")) { | |
560 JSONArray perms = permissions.getJSONArray("update"); | |
561 Actor actor = getActorFromPermissions(perms); | |
562 annot.setUpdatePermission(actor); | |
563 } | |
564 if (permissions.has("read")) { | |
565 JSONArray perms = permissions.getJSONArray("read"); | |
566 Actor actor = getActorFromPermissions(perms); | |
567 annot.setReadPermission(actor); | |
568 } | |
569 } | |
570 | |
16 | 571 /* |
572 * tags | |
573 */ | |
574 if (jo.has("tags")) { | |
575 HashSet<String> tagset = new HashSet<String>(); | |
576 JSONArray tags = jo.getJSONArray("tags"); | |
577 for (int i = 0; i < tags.length(); ++i) { | |
578 tagset.add(tags.getString(i)); | |
579 } | |
580 annot.setTags(tagset); | |
581 } | |
582 | |
583 | |
4 | 584 return annot; |
3 | 585 } |
586 | |
15 | 587 @SuppressWarnings("unused") // i in for loop |
10 | 588 protected Actor getActorFromPermissions(JSONArray perms) throws JSONException { |
589 Actor actor = null; | |
590 for (int i = 0; i < perms.length(); ++i) { | |
591 String perm = perms.getString(i); | |
592 if (perm.toLowerCase().startsWith("group:")) { | |
593 String groupId = perm.substring(6); | |
594 actor = new Group(groupId); | |
595 } else { | |
596 actor = new Person(perm); | |
597 } | |
598 // we just take the first one | |
599 break; | |
600 } | |
601 return actor; | |
602 } | |
603 | |
3 | 604 } |