source: AnnotationManagerN4J/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java @ 84:6bf38b5e30a8

Last change on this file since 84:6bf38b5e30a8 was 84:6bf38b5e30a8, checked in by casties, 9 years ago

also stores polygon shape image annotations.

File size: 28.0 KB
Line 
1/**
2 * Base class for Annotator resource classes.
3 */
4package de.mpiwg.itgroup.annotations.restlet;
5
6/*
7 * #%L
8 * AnnotationManager
9 * %%
10 * Copyright (C) 2012 - 2014 MPIWG Berlin
11 * %%
12 * This program is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License as
14 * published by the Free Software Foundation, either version 3 of the
15 * License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Lesser Public License for more details.
21 *
22 * You should have received a copy of the GNU General Lesser Public
23 * License along with this program.  If not, see
24 * <http://www.gnu.org/licenses/lgpl-3.0.html>.
25 * #L%
26 */
27
28import java.io.UnsupportedEncodingException;
29import java.security.InvalidKeyException;
30import java.security.SignatureException;
31import java.text.SimpleDateFormat;
32import java.util.ArrayList;
33import java.util.Calendar;
34import java.util.HashSet;
35import java.util.List;
36import java.util.Set;
37import java.util.logging.Logger;
38import java.util.regex.Matcher;
39import java.util.regex.Pattern;
40
41import net.oauth.jsontoken.Checker;
42import net.oauth.jsontoken.JsonToken;
43import net.oauth.jsontoken.JsonTokenParser;
44import net.oauth.jsontoken.SystemClock;
45import net.oauth.jsontoken.crypto.HmacSHA256Verifier;
46import net.oauth.jsontoken.crypto.Verifier;
47
48import org.apache.commons.codec.binary.Base64;
49import org.json.JSONArray;
50import org.json.JSONException;
51import org.json.JSONObject;
52import org.restlet.data.Status;
53import org.restlet.engine.header.Header;
54import org.restlet.representation.Representation;
55import org.restlet.resource.Options;
56import org.restlet.resource.ServerResource;
57import org.restlet.util.Series;
58
59import de.mpiwg.itgroup.annotations.Actor;
60import de.mpiwg.itgroup.annotations.Annotation;
61import de.mpiwg.itgroup.annotations.Annotation.FragmentTypes;
62import de.mpiwg.itgroup.annotations.Group;
63import de.mpiwg.itgroup.annotations.Person;
64import de.mpiwg.itgroup.annotations.Resource;
65import de.mpiwg.itgroup.annotations.Target;
66import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore;
67
68/**
69 * Base class for Annotator resource classes.
70 *
71 * @author dwinter, casties
72 *
73 */
74public abstract class AnnotatorResourceImpl extends ServerResource {
75
76    protected static Logger logger = Logger.getLogger(AnnotatorResourceImpl.class.toString());
77
78    private AnnotationStore store;
79
80    protected String getAllowedMethodsForHeader() {
81        return "OPTIONS,GET,POST";
82    }
83
84    protected AnnotationStore getAnnotationStore() {
85        if (store == null) {
86            store = ((BaseRestlet) getApplication()).getAnnotationStore();
87        }
88        return store;
89    }
90
91    public String encodeJsonId(String id) {
92        if (id == null)
93            return null;
94        try {
95            return Base64.encodeBase64URLSafeString(id.getBytes("UTF-8"));
96        } catch (UnsupportedEncodingException e) {
97            return null;
98        }
99    }
100
101    public String decodeJsonId(String id) {
102        if (id == null)
103            return null;
104        try {
105            return new String(Base64.decodeBase64(id), "UTF-8");
106        } catch (UnsupportedEncodingException e) {
107            return null;
108        }
109    }
110
111    /**
112     * Handle options request to allow CORS for AJAX.
113     *
114     * @param entity
115     */
116    @Options
117    public void doOptions(Representation entity) {
118        logger.fine("AnnotatorResourceImpl doOptions!");
119        setCorsHeaders();
120    }
121
122    /**
123     * set headers to allow CORS for AJAX.
124     */
125    protected void setCorsHeaders() {
126        @SuppressWarnings("unchecked")
127        Series<Header> responseHeaders = (Series<Header>) getResponse().getAttributes().get("org.restlet.http.headers");
128        if (responseHeaders == null) {
129            responseHeaders = new Series<Header>(Header.class);
130            getResponse().getAttributes().put("org.restlet.http.headers", responseHeaders);
131        }
132        responseHeaders.add("Access-Control-Allow-Methods", getAllowedMethodsForHeader());
133        // echo back Origin and Request-Headers
134        @SuppressWarnings("unchecked")
135        Series<Header> requestHeaders = (Series<Header>) getRequest().getAttributes().get("org.restlet.http.headers");
136        String origin = requestHeaders.getFirstValue("Origin", true);
137        if (origin == null) {
138            responseHeaders.add("Access-Control-Allow-Origin", "*");
139        } else {
140            responseHeaders.add("Access-Control-Allow-Origin", origin);
141        }
142        String allowHeaders = requestHeaders.getFirstValue("Access-Control-Request-Headers", true);
143        if (allowHeaders != null) {
144            responseHeaders.add("Access-Control-Allow-Headers", allowHeaders);
145        }
146        responseHeaders.add("Access-Control-Allow-Credentials", "true");
147        responseHeaders.add("Access-Control-Max-Age", "60");
148    }
149
150    /**
151     * returns if authentication information from headers is valid.
152     *
153     * @param entity
154     * @return
155     */
156    public boolean isAuthenticated(Representation entity) {
157        return (checkAuthToken(entity) != null);
158    }
159
160    /**
161     * Checks Annotator Auth plugin authentication information from headers.
162     * Returns userId if successful. Returns "anonymous" in non-authorization
163     * mode.
164     *
165     * @param entity
166     * @return
167     */
168    public String checkAuthToken(Representation entity) {
169        @SuppressWarnings("unchecked")
170        Series<Header> requestHeaders = (Series<Header>) getRequest().getAttributes().get("org.restlet.http.headers");
171        String authToken = requestHeaders.getFirstValue("x-annotator-auth-token", true);
172        if (authToken == null) {
173            if (!((BaseRestlet) getApplication()).isAuthorizationMode()) {
174                return "anonymous";
175            }
176            return null;
177        }
178        // decode token first to get consumer key
179        JsonToken token = new JsonTokenParser(null, null).deserialize(authToken);
180        String userId = token.getParamAsPrimitive("userId").getAsString();
181        String consumerKey = token.getParamAsPrimitive("consumerKey").getAsString();
182        // get stored consumer secret for key
183        BaseRestlet restServer = (BaseRestlet) getApplication();
184        String consumerSecret = restServer.getConsumerSecret(consumerKey);
185        logger.fine("requested consumer key=" + consumerKey + " secret=" + consumerSecret);
186        if (consumerSecret == null) {
187            return null;
188        }
189        // logger.fine(String.format("token=%s tokenString=%s signatureAlgorithm=%s",token,token.getTokenString(),token.getSignatureAlgorithm()));
190        try {
191            List<Verifier> verifiers = new ArrayList<Verifier>();
192            // we only do HS256 yet
193            verifiers.add(new HmacSHA256Verifier(consumerSecret.getBytes("UTF-8")));
194            // verify token signature(should really be static...)
195            new JsonTokenParser(new SystemClock(), null, (Checker[]) null).verify(token, verifiers);
196        } catch (SignatureException e) {
197            // TODO Auto-generated catch block
198            e.printStackTrace();
199        } catch (InvalidKeyException e) {
200            // TODO Auto-generated catch block
201            e.printStackTrace();
202        } catch (UnsupportedEncodingException e) {
203            // TODO Auto-generated catch block
204            e.printStackTrace();
205        }
206        // must be ok then
207        logger.fine("auth OK! user=" + userId);
208        return userId;
209    }
210
211    /**
212     * creates Annotator-JSON from an Annotation object.
213     *
214     * @param annot
215     * @param forAnonymous
216     *            TODO
217     * @return
218     */
219    public JSONObject createAnnotatorJson(Annotation annot, boolean forAnonymous) {
220        // return user as a JSON object (otherwise just as string)
221        boolean makeUserObject = true;
222        JSONObject jo = new JSONObject();
223        try {
224            jo.put("text", annot.getBodyText());
225            jo.put("uri", annot.getTargetBaseUri());
226            if (annot.getResourceUri() != null) {
227                jo.put("resource", annot.getResourceUri());
228            }
229            if (annot.getQuote() != null) {
230                jo.put("quote", annot.getQuote());
231            }
232
233            /*
234             * user
235             */
236            Actor creator = annot.getCreator();
237            if (creator != null) {
238                if (makeUserObject) {
239                    // create user object
240                    JSONObject userObject = new JSONObject();
241                    // save creator as uri
242                    userObject.put("uri", creator.getUri());
243                    // make short user id
244                    String userId = creator.getIdString();
245                    // set as id
246                    userObject.put("id", userId);
247                    // get full name
248                    String userName = creator.getName();
249                    if (userName == null) {
250                        BaseRestlet restServer = (BaseRestlet) getApplication();
251                        userName = restServer.getFullNameFromLdap(userId);
252                    }
253                    userObject.put("name", userName);
254                    // save user object
255                    jo.put("user", userObject);
256                } else {
257                    // save user as string
258                    jo.put("user", annot.getCreatorUri());
259                }
260            }
261
262            /*
263             * ranges
264             */
265            if (annot.getTargetFragment() != null) {
266                // we only look at the first xpointer
267                List<String> fragments = new ArrayList<String>();
268                fragments.add(annot.getTargetFragment());
269                FragmentTypes xt = annot.getFragmentType();
270                if (xt == FragmentTypes.XPOINTER) {
271                    jo.put("ranges", transformToRanges(fragments));
272                } else if (xt == FragmentTypes.AREA) {
273                    jo.put("shapes", transformToShapes(fragments));
274                } else if (xt == FragmentTypes.WKT) {
275                    jo.put("shapes", transformToShapes(fragments));
276                }
277            }
278
279            /*
280             * permissions
281             */
282            JSONObject perms = new JSONObject();
283            jo.put("permissions", perms);
284            // admin
285            JSONArray adminPerms = new JSONArray();
286            perms.put("admin", adminPerms);
287            Actor adminPerm = annot.getAdminPermission();
288            if (adminPerm != null) {
289                adminPerms.put(adminPerm.getIdString());
290            } else if (forAnonymous) {
291                // set something because its not allowed for anonymous
292                adminPerms.put("not-you");
293            }
294            // delete
295            JSONArray deletePerms = new JSONArray();
296            perms.put("delete", deletePerms);
297            Actor deletePerm = annot.getDeletePermission();
298            if (deletePerm != null) {
299                deletePerms.put(deletePerm.getIdString());
300            } else if (forAnonymous) {
301                // set something because its not allowed for anonymous
302                deletePerms.put("not-you");
303            }
304            // update
305            JSONArray updatePerms = new JSONArray();
306            perms.put("update", updatePerms);
307            Actor updatePerm = annot.getUpdatePermission();
308            if (updatePerm != null) {
309                updatePerms.put(updatePerm.getIdString());
310            } else if (forAnonymous) {
311                // set something because its not allowed for anonymous
312                updatePerms.put("not-you");
313            }
314            // read
315            JSONArray readPerms = new JSONArray();
316            perms.put("read", readPerms);
317            Actor readPerm = annot.getReadPermission();
318            if (readPerm != null) {
319                readPerms.put(readPerm.getIdString());
320            }
321
322            /*
323             * tags
324             */
325            Set<String> tagset = annot.getTags();
326            if (tagset != null) {
327                JSONArray tags = new JSONArray();
328                jo.put("tags", tags);
329                for (String tag : tagset) {
330                    tags.put(tag);
331                }
332            }
333
334            /*
335             * id
336             */
337            // encode Annotation URL (=id) in base64
338            String annotUrl = annot.getUri();
339            String annotId = encodeJsonId(annotUrl);
340            jo.put("id", annotId);
341            return jo;
342        } catch (JSONException e) {
343            logger.severe("Unable to create AnnotatorJSON! "+e);
344        }
345        return null;
346    }
347
348    private JSONArray transformToRanges(List<String> xpointers) {
349        JSONArray ja = new JSONArray();
350        Pattern rg = Pattern
351                .compile("xpointer\\(start-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)/range-to\\(end-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)\\)\\)");
352        Pattern rg1 = Pattern.compile("xpointer\\(start-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)\\)");
353        try {
354            for (String xpointer : xpointers) {
355                // String decoded = URLDecoder.decode(xpointer, "utf-8");
356                String decoded = xpointer;
357                Matcher m = rg.matcher(decoded);
358                if (m.find()) {
359                    JSONObject jo = new JSONObject();
360                    jo.put("start", m.group(1));
361                    jo.put("startOffset", m.group(2));
362                    jo.put("end", m.group(3));
363                    jo.put("endOffset", m.group(4));
364                    ja.put(jo);
365                }
366                m = rg1.matcher(xpointer);
367                if (m.find()) {
368                    JSONObject jo = new JSONObject();
369                    jo.put("start", m.group(1));
370                    jo.put("startOffset", m.group(2));
371                    ja.put(jo);
372                }
373            }
374        } catch (JSONException e) {
375            logger.severe("Unable to transform to ranges! "+e);
376        }
377        return ja;
378    }
379
380    private JSONArray transformToShapes(List<String> fragments) {
381        JSONArray ja = new JSONArray();
382        Pattern xywhPattern = Pattern.compile("xywh=(\\w*):([\\d\\.]+),([\\d\\.]+),([\\d\\.]+),([\\d\\.]+)");
383        Pattern wktPattern = Pattern.compile("wkt=(\\w+)\\(+([\\d\\.\\,\\ ]+)\\)+");
384        try {
385            for (String fragment : fragments) {
386                Matcher xywhMatch = xywhPattern.matcher(fragment);
387                Matcher wktMatch = wktPattern.matcher(fragment);
388                if (xywhMatch.find()) {
389                        // xywh rectangle fragment
390                    String units = xywhMatch.group(1);
391                    float x = getFloat(xywhMatch.group(2));
392                    float y = getFloat(xywhMatch.group(3));
393                    float width = getFloat(xywhMatch.group(4));
394                    float height = getFloat(xywhMatch.group(5));
395                    JSONObject shape = new JSONObject();
396                    JSONObject geom = new JSONObject();
397                    geom.put("units", units);
398                    geom.put("x", x);
399                    geom.put("y", y);
400                    if (width == 0 || height == 0) {
401                        shape.put("type", "point");
402                        shape.put("geometry", geom);
403                    } else {
404                        shape.put("type", "rectangle");
405                        geom.put("width", width);
406                        geom.put("height", height);
407                        shape.put("geometry", geom);
408                    }
409                    ja.put(shape);
410                } else if (wktMatch.find()) {
411                        // wkt shape fragment
412                        String type = wktMatch.group(1);
413                        String coordString = wktMatch.group(2);
414                    JSONObject shape = new JSONObject();
415                    JSONObject geom = new JSONObject();
416                    shape.put("type", type.toLowerCase());
417                    // TODO: add units/crs to fragment?
418                    geom.put("units", "fraction");
419                    JSONArray coords = new JSONArray();
420                    String[] coordPairs = coordString.split(", *");
421                    for (String coordPairString : coordPairs) {
422                        String[] coordPair = coordPairString.split(" +");
423                        coords.put(new JSONArray(coordPair));
424                    }
425                    geom.put("coordinates", coords);
426                        shape.put("geometry", geom);
427                        ja.put(shape);
428                }
429            }
430        } catch (JSONException e) {
431            logger.severe("Unable to transform to shapes! "+e);
432        }
433        return ja;
434    }
435
436    protected String parseShape(JSONObject shape) throws JSONException {
437        String fragment = null;
438        String type = shape.getString("type");
439        JSONObject geom = shape.getJSONObject("geometry");
440        if (type.equalsIgnoreCase("point")) {
441                // point shape
442            String x = geom.getString("x");
443            String y = geom.getString("y");
444            fragment = String.format("xywh=fraction:%s,%s,0,0", x, y);
445        } else if (type.equalsIgnoreCase("rectangle")) {
446                // rectangle shape
447            String x = geom.getString("x");
448            String y = geom.getString("y");
449            String width = geom.getString("width");
450            String height = geom.getString("height");
451            fragment = String.format("xywh=fraction:%s,%s,%s,%s", x, y, width, height);
452        } else if (type.equalsIgnoreCase("polygon")) {
453                // polygon shape
454                JSONArray coordArray = geom.getJSONArray("coordinates");
455            StringBuilder coords = new StringBuilder();
456            int numCoords = coordArray.length();
457                for (int i = 0; i < numCoords; ++i) {
458                        JSONArray coordPair = coordArray.getJSONArray(i);
459                        coords.append(coordPair.getString(0));
460                        coords.append(" ");
461                        coords.append(coordPair.getString(1));
462                        if (i < numCoords-1) {
463                                coords.append(", ");
464                        }
465                }
466                // TODO: add units/crs to wkt
467            fragment = String.format("wkt=POLYGON((%s))", coords);
468        } else {
469            logger.severe("Unable to parse this shape: " + shape);
470        }
471        return fragment;
472    }
473
474    protected String parseArea(JSONObject area) throws JSONException {
475        String x = area.getString("x");
476        String y = area.getString("y");
477        String width = "0";
478        String height = "0";
479        if (area.has("width")) {
480            width = area.getString("width");
481            height = area.getString("height");
482        }
483        String fragment = String.format("xywh=fraction:%s,%s,%s,%s", x, y, width, height);
484        return fragment;
485    }
486
487    protected String parseRange(JSONObject range) throws JSONException {
488        String start = range.getString("start");
489        String end = range.getString("end");
490        String startOffset = range.getString("startOffset");
491        String endOffset = range.getString("endOffset");
492        String fragment = String.format(
493                "xpointer(start-point(string-range(\"%s\",%s,1))/range-to(end-point(string-range(\"%s\",%s,1))))", start,
494                startOffset, end, endOffset);
495        return fragment;
496    }
497
498    /**
499     * Creates an Annotation object with data from JSON.
500     *
501     * uses the specification from the annotator project: {@link https
502     * ://github.com/okfn/annotator/wiki/Annotation-format}
503     *
504     * The username will be transformed to an URI if not given already as URI,
505     * if not it will set to the MPIWG namespace defined in
506     * de.mpiwg.itgroup.annotationManager.Constants.NS
507     *
508     * @param jo
509     * @return
510     * @throws JSONException
511     * @throws UnsupportedEncodingException
512     */
513    public Annotation createAnnotation(JSONObject jo, Representation entity) throws JSONException, UnsupportedEncodingException {
514        return updateAnnotation(new Annotation(), jo, entity);
515    }
516
517    /**
518     * Updates an Annotation object with data from JSON.
519     *
520     * uses the specification from the annotator project: {@link https
521     * ://github.com/okfn/annotator/wiki/Annotation-format}
522     *
523     * The username will be transformed to an URI if not given already as URI,
524     * if not it will set to the MPIWG namespace defined in
525     * de.mpiwg.itgroup.annotationManager.Constants.NS
526     *
527     * @param annot
528     * @param jo
529     * @return
530     * @throws JSONException
531     * @throws UnsupportedEncodingException
532     */
533    public Annotation updateAnnotation(Annotation annot, JSONObject jo, Representation entity) throws JSONException,
534            UnsupportedEncodingException {
535        /*
536         * target uri
537         */
538        if (jo.has("uri")) {
539            annot.setTarget(new Target(jo.getString("uri")));
540        }
541        /*
542         * resource uri
543         */
544        if (jo.has("resource")) {
545            annot.setResource(new Resource(jo.getString("resource")));
546        }
547        /*
548         * annotation text
549         */
550        if (jo.has("text")) {
551            annot.setBodyText(jo.getString("text"));
552        }
553        /*
554         * annotation quote
555         */
556        if (jo.has("quote")) {
557            annot.setQuote(jo.getString("quote"));
558        }
559        /*
560         * check authentication
561         */
562        String authUser = checkAuthToken(entity);
563        if (authUser == null) {
564            /*
565             * // try http auth User httpUser = getHttpAuthUser(entity); if
566             * (httpUser == null) {
567             */
568            setStatus(Status.CLIENT_ERROR_FORBIDDEN);
569            return null;
570            /*
571             * } authUser = httpUser.getIdentifier();
572             */
573        }
574        /*
575         * get or create creator object
576         */
577        Actor creator = annot.getCreator();
578        if (creator == null) {
579            creator = new Person();
580            annot.setCreator(creator);
581        }
582        // username not required, if no username given authuser will be used
583        String username = null;
584        String userUri = creator.getUri();
585        if (jo.has("user")) {
586            if (jo.get("user") instanceof String) {
587                // user is just a String
588                username = jo.getString("user");
589                creator.setId(username);
590                // TODO: what if username and authUser are different?
591            } else {
592                // user is an object
593                JSONObject user = jo.getJSONObject("user");
594                if (user.has("id")) {
595                    String id = user.getString("id");
596                    creator.setId(id);
597                    username = id;
598                }
599                if (user.has("uri")) {
600                    userUri = user.getString("uri");
601                }
602            }
603        }
604        if (username == null) {
605            username = authUser;
606        }
607        // try to get full name
608        if (creator.getName() == null && username != null) {
609            BaseRestlet restServer = (BaseRestlet) getApplication();
610            String fullName = restServer.getFullNameFromLdap(username);
611            creator.setName(fullName);
612        }
613        // userUri should be a URI, if not it will set to the MPIWG namespace
614        if (userUri == null) {
615            if (username.startsWith("http")) {
616                userUri = username;
617            } else {
618                userUri = BaseRestlet.PERSONS_URI_PREFIX + username;
619            }
620        }
621        // TODO: should we overwrite the creator?
622        if (creator.getUri() == null) {
623            creator.setUri(userUri);
624        }
625        /*
626         * creation date
627         */
628        if (annot.getCreated() == null) {
629            // set creation date
630            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
631            String ct = format.format(Calendar.getInstance().getTime());
632            annot.setCreated(ct);
633        }
634
635        /*
636         * create fragment from the first range/area
637         */
638        try {
639            if (jo.has("ranges")) {
640                JSONArray ranges = jo.getJSONArray("ranges");
641                if (ranges.length() > 0) {
642                    JSONObject range = ranges.getJSONObject(0);
643                    annot.setFragmentType(FragmentTypes.XPOINTER);
644                    String fragment = parseRange(range);
645                    annot.setTargetFragment(fragment);
646                }
647            }
648        } catch (JSONException e) {
649            // nothing to do
650        }
651        try {
652            if (jo.has("shapes")) {
653                JSONArray shapes = jo.getJSONArray("shapes");
654                if (shapes.length() > 0) {
655                    JSONObject shape = shapes.getJSONObject(0);
656                    String fragment = parseShape(shape);
657                    annot.setTargetFragment(fragment);
658                    if (fragment.startsWith("wkt=")) {
659                        annot.setFragmentType(FragmentTypes.WKT);
660                    } else {
661                        annot.setFragmentType(FragmentTypes.AREA);
662                    }
663                }
664            }
665        } catch (JSONException e) {
666            // nothing to do
667        }
668        // deprecated areas type
669        try {
670            if (jo.has("areas")) {
671                JSONArray areas = jo.getJSONArray("areas");
672                if (areas.length() > 0) {
673                    JSONObject area = areas.getJSONObject(0);
674                    annot.setFragmentType(FragmentTypes.AREA);
675                    String fragment = parseArea(area);
676                    annot.setTargetFragment(fragment);
677                }
678            }
679        } catch (JSONException e) {
680            // nothing to do
681        }
682        // no fragment is an error
683        if (annot.getFragmentType() == null || annot.getTargetFragment() == null) {
684            throw new JSONException("Annotation has no valid target fragment!");
685        }
686
687        /*
688         * permissions
689         */
690        if (jo.has("permissions")) {
691            JSONObject permissions = jo.getJSONObject("permissions");
692            if (permissions.has("admin")) {
693                JSONArray perms = permissions.getJSONArray("admin");
694                Actor actor = getActorFromPermissions(perms);
695                annot.setAdminPermission(actor);
696            }
697            if (permissions.has("delete")) {
698                JSONArray perms = permissions.getJSONArray("delete");
699                Actor actor = getActorFromPermissions(perms);
700                annot.setDeletePermission(actor);
701            }
702            if (permissions.has("update")) {
703                JSONArray perms = permissions.getJSONArray("update");
704                Actor actor = getActorFromPermissions(perms);
705                annot.setUpdatePermission(actor);
706            }
707            if (permissions.has("read")) {
708                JSONArray perms = permissions.getJSONArray("read");
709                Actor actor = getActorFromPermissions(perms);
710                annot.setReadPermission(actor);
711            }
712        }
713
714        /*
715         * tags
716         */
717        if (jo.has("tags")) {
718            HashSet<String> tagset = new HashSet<String>();
719            JSONArray tags = jo.getJSONArray("tags");
720            for (int i = 0; i < tags.length(); ++i) {
721                tagset.add(tags.getString(i));
722            }
723            annot.setTags(tagset);
724        }
725
726        return annot;
727    }
728
729    @SuppressWarnings("unused")
730    // i in for loop
731    protected Actor getActorFromPermissions(JSONArray perms) throws JSONException {
732        Actor actor = null;
733        for (int i = 0; i < perms.length(); ++i) {
734            String perm = perms.getString(i);
735            if (perm.toLowerCase().startsWith("group:")) {
736                String groupId = perm.substring(6);
737                actor = new Group(groupId);
738            } else {
739                actor = new Person(perm);
740            }
741            // we just take the first one
742            break;
743        }
744        return actor;
745    }
746
747    public static float getFloat(String s) {
748        try {
749            return Float.parseFloat(s);
750        } catch (NumberFormatException e) {
751        }
752        return 0f;
753    }
754
755    public static int getInt(String s) {
756        try {
757            return Integer.parseInt(s);
758        } catch (NumberFormatException e) {
759        }
760        return 0;
761    }
762}
Note: See TracBrowser for help on using the repository browser.