changeset 7:97f68ab3430f

support both read and search api of Annotator. some cleanup of imports.
author casties
date Mon, 19 Mar 2012 12:01:39 +0100
parents 5bb7cc86069c
children 11baadcdd2c8
files .classpath .settings/org.eclipse.wst.common.project.facet.core.xml src/de/mpiwg/itgroup/annotationManager/RDFHandling/RDFSearcher.java src/de/mpiwg/itgroup/annotationManager/restlet/AddAndReadAnnotations.java src/de/mpiwg/itgroup/annotationManager/restlet/AddAndSearchAnnotations.java src/de/mpiwg/itgroup/annotationManager/restlet/ExtendedAnnotationInput.java src/de/mpiwg/itgroup/annotationManager/restlet/RestServer.java src/de/mpiwg/itgroup/annotationManager/restlet/SearchAnnotations.java
diffstat 8 files changed, 1232 insertions(+), 701 deletions(-) [+]
line wrap: on
line diff
--- a/.classpath	Wed Mar 14 16:21:45 2012 +0100
+++ b/.classpath	Mon Mar 19 12:01:39 2012 +0100
@@ -1,16 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/JVM 1.6.0 (MacOS X Default)">
-		<attributes>
-			<attribute name="owner.project.facets" value="java"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/Apache Tomcat v6.0">
-		<attributes>
-			<attribute name="owner.project.facets" value="jst.web"/>
-		</attributes>
-	</classpathentry>
 	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/>
 	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
 	<classpathentry kind="lib" path="libs/log4j-1.2.15.jar">
@@ -46,5 +36,7 @@
 	</classpathentry>
 	<classpathentry kind="lib" path="libs/httpcomponents-core-4.0-beta3/lib/httpcore-nio-4.0-beta3.jar"/>
 	<classpathentry combineaccessrules="false" kind="src" path="/TripleStoreManager"/>
+	<classpathentry kind="lib" path="libs/org.restlet.jar"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/JDK 1.6"/>
 	<classpathentry kind="output" path="build/classes"/>
 </classpath>
--- a/.settings/org.eclipse.wst.common.project.facet.core.xml	Wed Mar 14 16:21:45 2012 +0100
+++ b/.settings/org.eclipse.wst.common.project.facet.core.xml	Mon Mar 19 12:01:39 2012 +0100
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <faceted-project>
-  <runtime name="Apache Tomcat v6.0"/>
   <fixed facet="jst.web"/>
   <fixed facet="wst.jsdt.web"/>
   <fixed facet="java"/>
--- a/src/de/mpiwg/itgroup/annotationManager/RDFHandling/RDFSearcher.java	Wed Mar 14 16:21:45 2012 +0100
+++ b/src/de/mpiwg/itgroup/annotationManager/RDFHandling/RDFSearcher.java	Mon Mar 19 12:01:39 2012 +0100
@@ -4,14 +4,11 @@
 import java.util.List;
 
 import org.apache.log4j.Logger;
-import org.apache.tiles.context.ListAttribute;
 import org.openrdf.query.BindingSet;
 import org.openrdf.query.TupleQueryResult;
 import org.restlet.Context;
 import org.restlet.engine.component.ChildContext;
 
-import sun.security.action.GetBooleanAction;
-
 import de.mpiwg.itgroup.annotationManager.Errors.TripleStoreSearchError;
 import de.mpiwg.itgroup.annotationManager.RDFHandling.Convert.Annotation;
 import de.mpiwg.itgroup.triplestoremanager.exceptions.TripleStoreHandlerException;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/de/mpiwg/itgroup/annotationManager/restlet/AddAndReadAnnotations.java	Mon Mar 19 12:01:39 2012 +0100
@@ -0,0 +1,683 @@
+//TODO: handle XML-Post des Annoteaprotocolls http://www.w3.org/2001/Annotea/User/Protocol.html
+
+package de.mpiwg.itgroup.annotationManager.restlet;
+
+import java.io.IOException;
+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.Post;
+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.Errors.TripleStoreStoreError;
+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 AddAndReadAnnotations 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);
+        }
+        String allowHeaders = requestHeaders.getFirstValue("Access-Control-Request-Headers", true);
+        if (allowHeaders != null) {
+            responseHeaders.add("Access-Control-Allow-Headers", allowHeaders);
+        }
+		responseHeaders.add("Access-Control-Allow-Methods", "POST,OPTIONS,GET");
+		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);
+		//TODO: Annotator read request does not use parameters
+		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;
+		} 
+
+		// annotator read request returns a list of annotation objects
+		logger.debug("sending:");
+		logger.debug(ja);
+		return new JsonRepresentation(ja);
+	}
+
+	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;
+
+
+
+
+
+	}
+
+
+	/**
+	 * 
+	 * 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) {
+
+		Annotation retVal = doPost(entity);
+		
+		
+//		JSONObject jo;
+//		try {
+//			jo = new JSONObject("{\"annotUrl\":\"" + retVal + "\"}");
+//		} catch (JSONException e) {
+//			setStatus(Status.SERVER_ERROR_INTERNAL);
+//			return null;
+//		}
+		
+		if (retVal==null)
+			return null;
+		JSONObject jo = annot2AnnotatorJSON(retVal);
+		JsonRepresentation retRep = new JsonRepresentation(jo);
+		return retRep;
+	}
+
+	@Post("html")
+	public Representation doPostHtml(Representation entity) {
+		Annotation retValAnnot = doPost(entity);
+		if (retValAnnot == null) {
+			return null;
+		}
+		
+		
+		String retVal=retValAnnot.annotationUri;
+		if (retVal == null) {
+			return null;
+		}
+		
+		String text = String.format(
+				"<html><body><a href=\"%s\">%s</a></body></html>", retVal
+				.replace(">", "").replace("<", ""),
+				retVal.replace(">", "&gt;").replace("<", "&lt;"));
+		Representation retRep = new StringRepresentation(text,
+				MediaType.TEXT_HTML);
+		return retRep;
+	}
+
+	public Convert.Annotation doPost(Representation entity) {
+		
+		doOptions(entity); 
+		Convert.Annotation annot;
+		// versuche basic authentifizierung und hole den Benutzer von dort.
+
+		// User authUser;= handleBasicAuthentification(entity);
+
+		if (entity.getMediaType().equals(MediaType.APPLICATION_JSON)) {
+
+			JsonRepresentation jrep;
+			try {
+				jrep = new JsonRepresentation(entity);
+			} catch (IOException e1) {
+				setStatus(Status.SERVER_ERROR_INTERNAL);
+				return null;
+			}
+
+			// try {
+			// logger.debug(jrep.getText());
+			// } catch (IOException e1) {
+			// // TODO Auto-generated catch block
+			// e1.printStackTrace();
+			// }
+			//
+
+			try {
+				JSONObject jo = jrep.getJsonObject();
+				if(jo==null){
+					setStatus(Status.SERVER_ERROR_INTERNAL);
+					return null;
+				}
+				
+				String mode=null;
+				if(jo.has("mode")){
+					mode = jo.getString("mode"); // hole modus
+				}
+				if (mode==null || mode.equals(""))
+					mode="annotea"; // default mode (annotea) TODO make this configurable
+					
+				if (mode.equals("annotator") ) { // annotator format
+					annot = handleAnnotatorSchema(jo, entity);
+					logger.debug("storing annotator object");
+					logger.debug(jo);
+				} else if (mode.equals("annotea")){
+					annot = handleAnnotea(jo, entity);
+				} else {
+					setStatus(Status.CLIENT_ERROR_BAD_REQUEST,"mode "+mode+"not supported!");
+					return null;
+				}
+
+			} catch (JSONException e) {
+				setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
+				return null;
+			}
+
+		} else if (entity.getMediaType().equals(MediaType.APPLICATION_WWW_FORM)) {
+			annot = handleForm(entity);
+
+		} else {
+			setStatus(Status.CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE);
+
+			return null;
+		}
+
+		if (annot==null){
+			return null;
+		}
+		if (annot.xpointer == null || annot.creator == null) {
+			setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
+
+			return null;
+		}
+
+
+
+		try {
+			return new Convert("file:///annotations").storeAnnotation(annot);
+		} catch (TripleStoreStoreError e) {
+			e.printStackTrace();
+			setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStore Error");
+			return null;
+		}
+	}
+
+	
+	/**
+	 * 
+	 * @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;
+	}
+
+	@Post
+	public Representation doPostHtml2(Representation entity) {
+		return doPostHtml(entity);
+	}
+
+	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);
+	}
+
+}
--- a/src/de/mpiwg/itgroup/annotationManager/restlet/AddAndSearchAnnotations.java	Wed Mar 14 16:21:45 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,683 +0,0 @@
-//TODO: handle XML-Post des Annoteaprotocolls http://www.w3.org/2001/Annotea/User/Protocol.html
-
-package de.mpiwg.itgroup.annotationManager.restlet;
-
-import java.io.IOException;
-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.Post;
-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.Errors.TripleStoreStoreError;
-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 AddAndSearchAnnotations 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);
-		}
-		responseHeaders.add("Access-Control-Allow-Origin", "*");
-		responseHeaders.add("Access-Control-Allow-Methods", "POST,OPTIONS,GET");
-		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", "false");
-		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 retObject = new JSONObject();
-		try {
-			retObject.put("rows",ja);
-			retObject.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(retObject);
-		return new JsonRepresentation(retObject);
-	}
-
-	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;
-
-
-
-
-
-	}
-
-
-	/**
-	 * 
-	 * 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) {
-
-		Annotation retVal = doPost(entity);
-		
-		
-//		JSONObject jo;
-//		try {
-//			jo = new JSONObject("{\"annotUrl\":\"" + retVal + "\"}");
-//		} catch (JSONException e) {
-//			setStatus(Status.SERVER_ERROR_INTERNAL);
-//			return null;
-//		}
-		
-		if (retVal==null)
-			return null;
-		JSONObject jo = annot2AnnotatorJSON(retVal);
-		JsonRepresentation retRep = new JsonRepresentation(jo);
-		return retRep;
-	}
-
-	@Post("html")
-	public Representation doPostHtml(Representation entity) {
-		Annotation retValAnnot = doPost(entity);
-		if (retValAnnot == null) {
-			return null;
-		}
-		
-		
-		String retVal=retValAnnot.annotationUri;
-		if (retVal == null) {
-			return null;
-		}
-		
-		String text = String.format(
-				"<html><body><a href=\"%s\">%s</a></body></html>", retVal
-				.replace(">", "").replace("<", ""),
-				retVal.replace(">", "&gt;").replace("<", "&lt;"));
-		Representation retRep = new StringRepresentation(text,
-				MediaType.TEXT_HTML);
-		return retRep;
-	}
-
-	public Convert.Annotation doPost(Representation entity) {
-		
-		doOptions(entity); 
-		Convert.Annotation annot;
-		// versuche basic authentifizierung und hole den Benutzer von dort.
-
-		// User authUser;= handleBasicAuthentification(entity);
-
-		if (entity.getMediaType().equals(MediaType.APPLICATION_JSON)) {
-
-			JsonRepresentation jrep;
-			try {
-				jrep = new JsonRepresentation(entity);
-			} catch (IOException e1) {
-				setStatus(Status.SERVER_ERROR_INTERNAL);
-				return null;
-			}
-
-			// try {
-			// logger.debug(jrep.getText());
-			// } catch (IOException e1) {
-			// // TODO Auto-generated catch block
-			// e1.printStackTrace();
-			// }
-			//
-
-			try {
-				JSONObject jo = jrep.getJsonObject();
-				if(jo==null){
-					setStatus(Status.SERVER_ERROR_INTERNAL);
-					return null;
-				}
-				
-				String mode=null;
-				if(jo.has("mode")){
-					mode = jo.getString("mode"); // hole modus
-				}
-				if (mode==null || mode.equals(""))
-					mode="annotea"; // default mode (annotea) TODO make this configurable
-					
-				if (mode.equals("annotator") ) { // annotator format
-					annot = handleAnnotatorSchema(jo, entity);
-					logger.debug("storing annotator object");
-					logger.debug(jo);
-				} else if (mode.equals("annotea")){
-					annot = handleAnnotea(jo, entity);
-				} else {
-					setStatus(Status.CLIENT_ERROR_BAD_REQUEST,"mode "+mode+"not supported!");
-					return null;
-				}
-
-			} catch (JSONException e) {
-				setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
-				return null;
-			}
-
-		} else if (entity.getMediaType().equals(MediaType.APPLICATION_WWW_FORM)) {
-			annot = handleForm(entity);
-
-		} else {
-			setStatus(Status.CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE);
-
-			return null;
-		}
-
-		if (annot==null){
-			return null;
-		}
-		if (annot.xpointer == null || annot.creator == null) {
-			setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
-
-			return null;
-		}
-
-
-
-		try {
-			return new Convert("file:///annotations").storeAnnotation(annot);
-		} catch (TripleStoreStoreError e) {
-			e.printStackTrace();
-			setStatus(Status.SERVER_ERROR_INTERNAL, "TripleStore Error");
-			return null;
-		}
-	}
-
-	
-	/**
-	 * 
-	 * @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;
-	}
-
-	@Post
-	public Representation doPostHtml2(Representation entity) {
-		return doPostHtml(entity);
-	}
-
-	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);
-	}
-
-}
--- a/src/de/mpiwg/itgroup/annotationManager/restlet/ExtendedAnnotationInput.java	Wed Mar 14 16:21:45 2012 +0100
+++ b/src/de/mpiwg/itgroup/annotationManager/restlet/ExtendedAnnotationInput.java	Mon Mar 19 12:01:39 2012 +0100
@@ -32,10 +32,11 @@
 	        responseHeaders = new Form();
 	        getResponse().getAttributes().put("org.restlet.http.headers", responseHeaders);
 	    }
+	    // TODO: better to answer Allow-Origin with the requested Origin
 	    responseHeaders.add("Access-Control-Allow-Origin", "*");
 	    responseHeaders.add("Access-Control-Allow-Methods", "POST,OPTIONS,GET");
 	    responseHeaders.add("Access-Control-Allow-Headers", "Content-Type");
-	    responseHeaders.add("Access-Control-Allow-Credentials", "false");
+	    responseHeaders.add("Access-Control-Allow-Credentials", "true");
 	    responseHeaders.add("Access-Control-Max-Age", "60");
 	}
 
--- a/src/de/mpiwg/itgroup/annotationManager/restlet/RestServer.java	Wed Mar 14 16:21:45 2012 +0100
+++ b/src/de/mpiwg/itgroup/annotationManager/restlet/RestServer.java	Mon Mar 19 12:01:39 2012 +0100
@@ -89,7 +89,7 @@
     }
 
 	/**
-	 * Konfiguration fŸr den Authentificator in Jaas. Pfad zum JAAS-Konfigurationsfile liegt im Context-Parameter 
+	 * Konfiguration f�r den Authentificator in Jaas. Pfad zum JAAS-Konfigurationsfile liegt im Context-Parameter 
 	 * "de.mpiwg.itgroup.annotationManager.jaas.configFilePath".
 	 * @return
 	 */
@@ -133,8 +133,8 @@
 		Router router = new Router(getContext());
 		
 		
-		router.attach("/annotations",AddAndSearchAnnotations.class);
-		router.attach("/search",AddAndSearchAnnotations.class); // annotator api askes for different uris for search and adding
+		router.attach("/annotations",AddAndReadAnnotations.class);
+		router.attach("/search",SearchAnnotations.class); // annotator api askes for different uris for search and adding
 		router.attach("/dummy",Dummy.class);
 		
 		//router.attach("",redirector);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/de/mpiwg/itgroup/annotationManager/restlet/SearchAnnotations.java	Mon Mar 19 12:01:39 2012 +0100
@@ -0,0 +1,542 @@
+//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);
+	}
+
+}