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