Mercurial > hg > AnnotationManager
view src/de/mpiwg/itgroup/annotationManager/restlet/SearchAnnotations.java @ 8:11baadcdd2c8
start of new Annotator API implementation.
author | casties |
---|---|
date | Mon, 19 Mar 2012 14:50:28 +0100 |
parents | 97f68ab3430f |
children | 667d98fd28bd |
line wrap: on
line source
//TODO: handle XML-Post des Annoteaprotocolls http://www.w3.org/2001/Annotea/User/Protocol.html package de.mpiwg.itgroup.annotationManager.restlet; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.log4j.Logger; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.restlet.Context; import org.restlet.data.ClientInfo; import org.restlet.data.Form; import org.restlet.data.MediaType; 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.Get; import org.restlet.resource.Options; import org.restlet.resource.ServerResource; import org.restlet.security.User; import de.mpiwg.itgroup.annotationManager.Constants.NS; import de.mpiwg.itgroup.annotationManager.Errors.TripleStoreSearchError; import de.mpiwg.itgroup.annotationManager.RDFHandling.Convert; import de.mpiwg.itgroup.annotationManager.RDFHandling.Convert.Annotation; 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; public class SearchAnnotations extends ServerResource { private Logger logger = Logger.getRootLogger(); @Options public void doOptions(Representation entity) { Form responseHeaders = (Form) getResponse().getAttributes().get( "org.restlet.http.headers"); if (responseHeaders == null) { responseHeaders = new Form(); getResponse().getAttributes().put("org.restlet.http.headers", responseHeaders); } Form requestHeaders = (Form) getRequest().getAttributes().get("org.restlet.http.headers"); String origin = requestHeaders.getFirstValue("Origin", true); if (origin == null) { responseHeaders.add("Access-Control-Allow-Origin", "*"); } else { responseHeaders.add("Access-Control-Allow-Origin", origin); } responseHeaders.add("Access-Control-Allow-Methods", "OPTIONS,GET"); String allowHeaders = requestHeaders.getFirstValue("Access-Control-Request-Headers", true); if (allowHeaders != null) { responseHeaders.add("Access-Control-Allow-Headers", allowHeaders); } //responseHeaders.add("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, X-Annotator-Account-Id, X-Annotator-User-Id, X-Annotator-Auth-Token-Valid-Until, X-Annotator-Auth-Token"); responseHeaders.add("Access-Control-Allow-Credentials", "true"); responseHeaders.add("Access-Control-Max-Age", "60"); } @Get("html") public Representation doGetHTML(Representation entity){ doOptions(entity); Form form = getRequest().getResourceRef().getQueryAsForm(); String uri = form.getFirstValue("uri"); String user = form.getFirstValue("user"); String limit=form.getFirstValue("limit"); String offset=form.getFirstValue("offset"); try { if (uri!=null){ uri = URLDecoder.decode(uri, "utf-8"); } } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); setStatus(Status.CLIENT_ERROR_NOT_ACCEPTABLE); return null; } RDFSearcher searcher = new RDFSearcher("file:///annotations"); //TODO should ge into config file String retString="<html><body><table>"; String lineFormat="<tr><td><a href=\"%s\">%s</a></td>" + "<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>"; try { List<Convert.Annotation> annots=searcher.search(uri,user,limit,offset); for (Convert.Annotation annot:annots){ RestServer restServer = (RestServer) getApplication(); String userName=restServer.getUserNameFromLdap(annot.creator); List<String> xpointer = new ArrayList<String>(); if (annot.xpointers==null || annot.xpointers.size()==0) retString+=String.format(lineFormat, userName,userName,annot.url,annot.url,annot.time,annot.text,annot.xpointer,annot.xpointer,annot.annotationUri,annot.annotationUri); else { for(String xpointerString:annot.xpointers){ retString+=String.format(lineFormat, userName,userName,annot.url,annot.url,annot.time,annot.text,xpointerString,xpointerString,annot.annotationUri,annot.annotationUri); } } } } catch (TripleStoreHandlerException e) { // TODO Auto-generated catch block e.printStackTrace(); setStatus(Status.SERVER_ERROR_INTERNAL,"TripleStoreHandler Error"); return null; } catch (TripleStoreSearchError e) { // TODO Auto-generated catch block e.printStackTrace(); setStatus(Status.SERVER_ERROR_INTERNAL,"TripleStoreSearch Error"); return null; } retString+="</table></body></html>"; logger.debug("sending:"); logger.debug(retString); return new StringRepresentation(retString,MediaType.TEXT_HTML); } /** * Erzeugt aus einer Annotation, das f�r den Annotator notwendige JSON-Format * @param annot * @return */ public JSONObject annot2AnnotatorJSON(Convert.Annotation annot){ JSONObject jo = new JSONObject(); try { jo.put("text", annot.text); jo.put("uri",annot.url); JSONObject userObject= new JSONObject(); userObject.put("id",annot.creator); RestServer restServer = (RestServer) getApplication(); String userID= annot.creator; if (userID.startsWith(NS.MPIWG_PERSONS)){ userID=userID.replace(NS.MPIWG_PERSONS, ""); //entferne NAMESPACE } String userName=restServer.getUserNameFromLdap(userID); userObject.put("name",userName); jo.put("user",userObject); List<String> xpointer = new ArrayList<String>(); if (annot.xpointers==null || annot.xpointers.size()==0) xpointer.add(annot.xpointer); else { for(String xpointerString:annot.xpointers){ xpointer.add(xpointerString); } } jo.put("ranges", transformToRanges(xpointer)); jo.put("id", annot.annotationUri); return jo; } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } } @Get("json") public Representation doGetJSON(Representation entity){ doOptions(entity); Form form = getRequest().getResourceRef().getQueryAsForm(); String uri = form.getFirstValue("uri"); String user = form.getFirstValue("user"); String limit=form.getFirstValue("limit"); String offset=form.getFirstValue("offset"); // RDFSearcher searcher = new RDFSearcher("file:///annotations"); //TODO should ge into config file JSONArray ja; try { List<Convert.Annotation> annots=searcher.search(uri,user,limit,offset); ja = new JSONArray(); for (Convert.Annotation annot:annots){ // JSONObject jo = new JSONObject(); // jo.put("text", annot.text); // jo.put("uri",annot.url); // // JSONObject userObject= new JSONObject(); // userObject.put("id",annot.creator); // // RestServer restServer = (RestServer) getApplication(); // // String userID= annot.creator; // if (userID.startsWith(NS.MPIWG_PERSONS)){ // userID=userID.replace(NS.MPIWG_PERSONS, ""); //entferne NAMESPACE // } // String userName=restServer.getUserNameFromLdap(userID); // userObject.put("name",userName); // // jo.put("user",userObject); // // List<String> xpointer = new ArrayList<String>(); // // if (annot.xpointers==null || annot.xpointers.size()==0) // xpointer.add(annot.xpointer); // else { // for(String xpointerString:annot.xpointers){ // xpointer.add(xpointerString); // } // } // jo.put("ranges", transformToRanges(xpointer)); JSONObject jo = annot2AnnotatorJSON(annot); if (jo!=null){ ja.put(annot2AnnotatorJSON(annot)); } else { setStatus(Status.SERVER_ERROR_INTERNAL,"JSon Error"); return null; } } } catch (TripleStoreHandlerException e) { // TODO Auto-generated catch block e.printStackTrace(); setStatus(Status.SERVER_ERROR_INTERNAL,"TripleStoreHandler Error"); return null; } catch (TripleStoreSearchError e) { // TODO Auto-generated catch block e.printStackTrace(); setStatus(Status.SERVER_ERROR_INTERNAL,"TripleStoreSearch Error"); return null; } JSONObject result = new JSONObject(); try { result.put("rows",ja); result.put("total",ja.length()); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); setStatus(Status.SERVER_ERROR_INTERNAL,"JSon Error"); return null; } logger.debug("sending:"); logger.debug(result); return new JsonRepresentation(result); } private JSONArray transformToRanges(List<String> xpointers) { JSONArray ja = new JSONArray(); Pattern rg = Pattern.compile("#xpointer\\(start-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)/range-to\\(end-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)\\)\\)"); Pattern rg1 = Pattern.compile("#xpointer\\(start-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)\\)"); try { for(String xpointer:xpointers){ String decoded =URLDecoder.decode(xpointer,"utf-8"); Matcher m=rg.matcher(decoded); if (m.find()){ { JSONObject jo = new JSONObject(); jo.put("start", m.group(1)); jo.put("startOffset", m.group(2)); jo.put("end", m.group(3)); jo.put("endOffset", m.group(4)); ja.put(jo); } } m=rg1.matcher(xpointer); if (m.find()){ JSONObject jo = new JSONObject(); jo.put("start", m.group(1)); jo.put("startOffset", m.group(2)); ja.put(jo); } } } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return ja; } /** * * @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 Convert.Annotation handleForm(Representation entity) { Convert.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 = handleBasicAuthentification(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+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 Convert.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 Convert.Annotation(xpointer, username, null, text, type, url); return annot; } private User handleBasicAuthentification(Representation entity) { RestServer restServer = (RestServer) getApplication(); if (!restServer.authenticate(getRequest(), getResponse())) { // Not authenticated return null; } ClientInfo ci = getRequest().getClientInfo(); logger.debug(ci); return getRequest().getClientInfo().getUser(); } /** * using a minimal annotation format based on the annotea specification * * @param jo * must contain xpointer, text,url,type and can contain a * username, if not the username form the authentification will * be used. * @param authUser * user object * 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 * @return * @throws JSONException */ public Annotation handleAnnotea(JSONObject jo, Representation entity) throws JSONException { User authUser = handleBasicAuthentification(entity); String username = jo.getString("username"); // not required, if no // username given authuser // will be used. String xpointer = jo.getString("xpointer"); String text = null; if (jo.has("text")) text = jo.getString("text"); String url = null; if (jo.has("url")) url = jo.getString("url"); String type = null; if (jo.has("type")) type = jo.getString("type"); if (username == null) 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 if (!username.startsWith("http")) username=NS.MPIWG_PERSONS+username; return new Convert.Annotation(xpointer, username, null, text, type, url); } /** * uses the specification from the annotator project. * * @see{https://github.com/okfn/annotator/wiki/Annotation-format} The user * object must * contain an * id and * password or * basic * authentification * is used. * 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 * @param jo * @param authUser * @return * @throws JSONException */ public Convert.Annotation handleAnnotatorSchema(JSONObject jo, Representation entity) throws JSONException { Convert.Annotation annot; String url = jo.getString("uri"); String text = jo.getString("text"); String username = null; if (jo.has("user")) { // not required, if no username given authuser // will be used otherwise username and password // has to be submitted JSONObject user = jo.getJSONObject("user"); if (user.has("id")) { username = user.getString("id"); if(!user.has("password")){ User authUser = handleBasicAuthentification(entity); if (authUser==null){ setStatus(Status.CLIENT_ERROR_FORBIDDEN); return null; } username = authUser.getIdentifier(); } else { String password = user.getString("password"); if (!((RestServer) getApplication()).authenticate(username, password, getRequest())) { setStatus(Status.CLIENT_ERROR_FORBIDDEN); return null; } } } } else { User authUser = handleBasicAuthentification(entity); if (authUser == null) { setStatus(Status.CLIENT_ERROR_FORBIDDEN); return null; } username = authUser.getIdentifier(); } String xpointer; if (jo.has("ranges")) { JSONObject ranges = jo.getJSONArray("ranges").getJSONObject(0); String start = ranges.getString("start"); String end = ranges.getString("end"); String startOffset = ranges.getString("startOffset"); String endOffset = ranges.getString("endOffset"); try { xpointer = url+"#"+ URLEncoder.encode(String.format( "xpointer(start-point(string-range(\"%s\",%s,1))/range-to(end-point(string-range(\"%s\",%s,1))))", start, startOffset, end, endOffset),"utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); setStatus(Status.SERVER_ERROR_INTERNAL); return null; } } else { xpointer = url; } //username should be a URI, if not it will set to the MPIWG namespace defined in de.mpiwg.itgroup.annotationManager.Constants.NS if (!username.startsWith("http")) username=NS.MPIWG_PERSONS+username; return new Convert.Annotation(xpointer, username, null, text, null); } }