Mercurial > hg > AnnotationManagerN4J
diff src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorAnnotations.java @ 3:47b53ae385d1
merging old code
author | casties |
---|---|
date | Fri, 29 Jun 2012 20:38:27 +0200 |
parents | |
children | 3599b29c393f |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorAnnotations.java Fri Jun 29 20:38:27 2012 +0200 @@ -0,0 +1,398 @@ +/** + * Implements the "annotations" uri of the Annotator API. see + * <https://github.com/okfn/annotator/wiki/Storage> + */ +package de.mpiwg.itgroup.annotations.restlet; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.restlet.Context; +import org.restlet.data.Form; +import org.restlet.data.MediaType; +import org.restlet.data.Reference; +import org.restlet.data.Status; +import org.restlet.ext.json.JsonRepresentation; +import org.restlet.representation.Representation; +import org.restlet.representation.StringRepresentation; +import org.restlet.resource.Delete; +import org.restlet.resource.Get; +import org.restlet.resource.Post; +import org.restlet.resource.Put; +import org.restlet.security.User; + +import de.mpiwg.itgroup.annotationManager.Constants.NS; +import de.mpiwg.itgroup.annotationManager.Errors.TripleStoreSearchError; +import de.mpiwg.itgroup.annotationManager.Errors.TripleStoreStoreError; +import de.mpiwg.itgroup.annotationManager.RDFHandling.Annotation; +import de.mpiwg.itgroup.annotationManager.RDFHandling.Convert; +import de.mpiwg.itgroup.annotationManager.RDFHandling.RDFSearcher; +import de.mpiwg.itgroup.annotationManager.drupal.AnnotationHandler; +import de.mpiwg.itgroup.annotationManager.drupal.UnknowUserException; +import de.mpiwg.itgroup.triplestoremanager.exceptions.TripleStoreHandlerException; + +/** + * Implements the "annotations" uri of the Annotator API. see <https://github.com/okfn/annotator/wiki/Storage> + * + * @author dwinter, casties + * + */ +public class AnnotatorAnnotations extends AnnotatorResourceImpl { + + protected String getAllowedMethodsForHeader() { + return "OPTIONS,GET,POST,PUT,DELETE"; + } + + /** + * GET with JSON content-type. + * + * @param entity + * @return + */ + @Get("json") + public Representation doGetJSON(Representation entity) { + logger.debug("AnnotatorAnnotations doGetJSON!"); + setCorsHeaders(); + // id from URI /annotations/{id} + String jsonId = (String) getRequest().getAttributes().get("id"); + String id = decodeJsonId(jsonId); + logger.debug("annotation-id=" + id); + + // TODO: what to return without id - list of all annotations? + + // TODO: what to do with authentication? + boolean authenticated = isAuthenticated(entity); + logger.debug("request authenticated=" + authenticated); + + RDFSearcher searcher = new RDFSearcher(NS.MPIWG_ANNOT_CTX); // TODO should ge into config file + + try { + List<Annotation> annots = searcher.searchById(id); + if (annots.size() == 1) { + // there should be only one + JSONObject result = createAnnotatorJson(annots.get(0)); + logger.debug("sending:"); + logger.debug(result); + return new JsonRepresentation(result); + } else { + JSONArray results; + results = new JSONArray(); + for (Annotation annot : annots) { + JSONObject jo = createAnnotatorJson(annot); + if (jo != null) { + results.put(createAnnotatorJson(annot)); + } else { + setStatus(Status.SERVER_ERROR_INTERNAL, "JSon Error"); + return null; + } + } + // annotator read request returns a list of annotation objects + logger.debug("sending:"); + logger.debug(results); + return new JsonRepresentation(results); + } + } catch (TripleStoreHandlerException e) { + e.printStackTrace(); + setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStoreHandler Error"); + return null; + } catch (TripleStoreSearchError e) { + e.printStackTrace(); + setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStoreSearch Error"); + return null; + } + } + + /** + * POST with JSON content-type. + * + * json hash: username: name des users xpointer: xpointer auf den Ausschnitt (incl. der URL des Dokumentes) text: text der + * annotation annoturl: url auf eine Annotation falls extern + * + * @return + */ + @Post("json") + public Representation doPostJson(Representation entity) { + logger.debug("AnnotatorAnnotations doPostJSON!"); + // set headers + setCorsHeaders(); + Annotation annot = null; + try { + JsonRepresentation jrep = new JsonRepresentation(entity); + JSONObject jo = jrep.getJsonObject(); + if (jo == null) { + setStatus(Status.SERVER_ERROR_INTERNAL); + return null; + } + // make sure id is not set for POST + jo.remove("id"); + // get Annotation object from posted JSON + annot = createAnnotation(jo, entity); + } catch (IOException e1) { + setStatus(Status.SERVER_ERROR_INTERNAL); + return null; + } catch (JSONException e) { + setStatus(Status.CLIENT_ERROR_BAD_REQUEST); + return null; + } + if (annot == null || annot.xpointer == null || annot.creator == null) { + setStatus(Status.CLIENT_ERROR_BAD_REQUEST); + return null; + } + Annotation storedAnnot; + try { + // store Annotation + storedAnnot = new Convert(NS.MPIWG_ANNOT_CTX).storeAnnotation(annot); + } catch (TripleStoreStoreError e) { + e.printStackTrace(); + setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStore Error"); + return null; + } + /* according to https://github.com/okfn/annotator/wiki/Storage + * we should return 303: see other. + * For now we return the annotation. + */ + JSONObject jo = createAnnotatorJson(storedAnnot); + JsonRepresentation retRep = new JsonRepresentation(jo); + return retRep; + } + + /** + * POST with HTML content-type. + * + * @param entity + * @return + */ + @Post("html") + public Representation doPostHtml(Representation entity) { + logger.debug("AnnotatorAnnotations doPostHtml!"); + Annotation annot; + annot = handleForm(entity); + if (annot.xpointer == null || annot.creator == null) { + setStatus(Status.CLIENT_ERROR_BAD_REQUEST); + + return null; + } + + Annotation retValAnnot; + try { + retValAnnot = new Convert(NS.MPIWG_ANNOT_CTX).storeAnnotation(annot); + } catch (TripleStoreStoreError e) { + e.printStackTrace(); + setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStore Error"); + return null; + } + if (retValAnnot == null) { + return null; + } + String retVal = retValAnnot.getAnnotationUri(); + if (retVal == null) { + return null; + } + + String text = String.format("<html><body><a href=\"%s\">%s</a></body></html>", retVal.replace(">", "").replace("<", ""), + retVal.replace(">", ">").replace("<", "<")); + Representation retRep = new StringRepresentation(text, MediaType.TEXT_HTML); + return retRep; + } + + /** + * + * @param entity + * should contain a form with the parameters "username", "password", "xpointer","text","uri","type" + * + * username,password is optional, if not given BasicAuthentification is used. + * + * 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 + * + * @return + */ + protected Annotation handleForm(Representation entity) { + Annotation annot; + Form form = new Form(entity); + String username = form.getValues("username"); + String mode = form.getValues("mode"); + String password = form.getValues("password"); + String xpointer = form.getValues("xpointer"); + String text = form.getValues("text"); + String title = form.getValues("title"); + String url = form.getValues("url"); + String type = form.getValues("type"); + RestServer restServer = (RestServer) getApplication(); + + // falls user and password nicht null sind: + User userFromForm = null; + if (username != null && password != null) { + if (restServer.authenticate(username, password, getRequest())) { + userFromForm = new User(username); + } + } + User authUser = null; + + if (userFromForm == null) { + authUser = getHttpAuthUser(entity); + } + + // weder BasicAuth noch FormAuth + if (authUser == null && userFromForm == null) { + setStatus(Status.CLIENT_ERROR_FORBIDDEN); + return null; + } + + if (userFromForm != null) { + username = userFromForm.getIdentifier(); + } else { + username = authUser.getIdentifier(); + } + + // username should be a URI, if not it will set to the MPIWG namespace defined in + // de.mpiwg.itgroup.annotationManager.Constants.NS + String usernameOrig = username; + if (!username.startsWith("http")) + username = NS.MPIWG_PERSONS_URL + username; + + if (mode.equals("complexAnnotation")) {// Annotation mit text in externer ressource + + Context context = getContext(); + String drupalPath = context.getParameters().getFirstValue("de.mpiwg.itgroup.annotationManager.drupalServer"); + + AnnotationHandler ah = new AnnotationHandler(drupalPath); + JSONObject newAnnot; + try { + newAnnot = ah.createAnnotation(title, text, usernameOrig, password); + } catch (UnknowUserException e1) { + setStatus(Status.CLIENT_ERROR_FORBIDDEN); + e1.printStackTrace(); + return null; + } + try { + annot = new Annotation(xpointer, username, null, text, type, newAnnot.getString("node_uri")); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + setStatus(Status.SERVER_ERROR_INTERNAL); + return null; + } + } else + annot = new Annotation(xpointer, username, null, text, type, url); + return annot; + } + + + /** + * PUT with JSON content-type. + * + * @param entity + * @return + */ + @Put("json") + public Representation doPutJSON(Representation entity) { + logger.debug("AnnotatorAnnotations doPutJSON!"); + setCorsHeaders(); + // id from URI /annotations/{id} + String jsonId = (String) getRequest().getAttributes().get("id"); + String id = decodeJsonId(jsonId); + logger.debug("annotation-id=" + id); + + // TODO: what to do with authentication? we should check the owner + boolean authenticated = isAuthenticated(entity); + logger.debug("request authenticated=" + authenticated); + if (!authenticated) { + setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!"); + return null; + } + + Annotation annot = null; + try { + JsonRepresentation jrep = new JsonRepresentation(entity); + JSONObject jo = jrep.getJsonObject(); + if (jo == null) { + setStatus(Status.CLIENT_ERROR_BAD_REQUEST); + return null; + } + RDFSearcher searcher = new RDFSearcher(NS.MPIWG_ANNOT_CTX); // TODO should ge into config file + // get stored Annotation + List<Annotation> annots = searcher.searchById(id); + if (annots.size() < 1) { + setStatus(Status.CLIENT_ERROR_NOT_FOUND); + return null; + } + Annotation storedAnnot = annots.get(0); + // delete + searcher.deleteById(id); + // update from posted JSON + annot = updateAnnotation(storedAnnot, jo, entity); + // store Annotation + storedAnnot = new Convert(NS.MPIWG_ANNOT_CTX).storeAnnotation(annot); + /* according to https://github.com/okfn/annotator/wiki/Storage + * we should return 303: see other. + * but the client doesn't like it + setStatus(Status.REDIRECTION_SEE_OTHER); + // go to same URL as this one + Reference thisUrl = this.getReference(); + this.getResponse().setLocationRef(thisUrl); */ + // return new annotation + jo = createAnnotatorJson(storedAnnot); + JsonRepresentation retRep = new JsonRepresentation(jo); + return retRep; + } catch (TripleStoreHandlerException e) { + e.printStackTrace(); + setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStoreHandler Error"); + } catch (TripleStoreSearchError e) { + e.printStackTrace(); + setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStoreSearch Error"); + } catch (JSONException e) { + e.printStackTrace(); + setStatus(Status.CLIENT_ERROR_BAD_REQUEST); + } catch (IOException e) { + e.printStackTrace(); + setStatus(Status.SERVER_ERROR_INTERNAL, "Other Error"); + } + return null; + } + + /** + * DELETE with JSON content-type. + * + * @param entity + * @return + */ + @Delete("json") + public Representation doDeleteJSON(Representation entity) { + logger.debug("AnnotatorAnnotations doDeleteJSON!"); + setCorsHeaders(); + // id from URI /annotations/{id} + String jsonId = (String) getRequest().getAttributes().get("id"); + String id = decodeJsonId(jsonId); + logger.debug("annotation-id=" + id); + + // TODO: what to do with authentication? we should check the owner + boolean authenticated = isAuthenticated(entity); + logger.debug("request authenticated=" + authenticated); + if (!authenticated) { + setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!"); + return null; + } + + RDFSearcher searcher = new RDFSearcher(NS.MPIWG_ANNOT_CTX); // TODO should ge into config file + + try { + // delete annotation + searcher.deleteById(id); + setStatus(Status.SUCCESS_NO_CONTENT); + } catch (TripleStoreHandlerException e) { + e.printStackTrace(); + setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStoreHandler Error"); + } catch (TripleStoreSearchError e) { + e.printStackTrace(); + setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStoreSearch Error"); + } + return null; + } + + +}