changeset 5:bbf0cc5bee29

version 0.2 really works now
author casties
date Tue, 03 Jul 2012 21:23:17 +0200
parents 3599b29c393f
children 6dfbe2400f64
files pom.xml src/main/java/de/mpiwg/itgroup/annotations/Annotation.java src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java src/main/java/de/mpiwg/itgroup/annotations/restlet/RestServer.java
diffstat 5 files changed, 182 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- a/pom.xml	Mon Jul 02 22:39:46 2012 +0200
+++ b/pom.xml	Tue Jul 03 21:23:17 2012 +0200
@@ -3,7 +3,7 @@
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>de.mpiwg.itgroup.annotations</groupId>
 	<artifactId>AnnotationManagerN4J</artifactId>
-	<version>0.0.1-SNAPSHOT</version>
+	<version>0.2.0-SNAPSHOT</version>
 	<properties>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<neo4j-version>1.7.1</neo4j-version>
@@ -21,11 +21,11 @@
 				<enabled>false</enabled>
 			</snapshots>
 		</repository>
-        <repository>
-            <id>maven-restlet</id>
-            <name>Public online Restlet repository</name>
-            <url>http://maven.restlet.org</url>
-        </repository>
+		<repository>
+			<id>maven-restlet</id>
+			<name>Public online Restlet repository</name>
+			<url>http://maven.restlet.org</url>
+		</repository>
 	</repositories>
 	<dependencies>
 		<dependency>
@@ -70,18 +70,19 @@
 				</exclusion>
 			</exclusions>
 		</dependency>
-        <dependency>
-            <groupId>log4j</groupId>
-            <artifactId>log4j</artifactId>
-            <version>1.2.14</version>
-        </dependency>
-        <dependency>
-        	<groupId>commons-codec</groupId>
-        	<artifactId>commons-codec</artifactId>
-        	<version>1.4</version>
-        </dependency>
+		<dependency>
+			<groupId>log4j</groupId>
+			<artifactId>log4j</artifactId>
+			<version>1.2.14</version>
+		</dependency>
+		<dependency>
+			<groupId>commons-codec</groupId>
+			<artifactId>commons-codec</artifactId>
+			<version>1.4</version>
+		</dependency>
 	</dependencies>
 	<build>
+		<finalName>AnnotationManager</finalName>
 		<pluginManagement>
 			<plugins>
 				<plugin>
--- a/src/main/java/de/mpiwg/itgroup/annotations/Annotation.java	Mon Jul 02 22:39:46 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/Annotation.java	Tue Jul 03 21:23:17 2012 +0200
@@ -52,6 +52,11 @@
     protected String creatorUri;
     
     /**
+     * The full name of the creator of this annotation.
+     */
+    protected String creatorName;
+    
+    /**
      * The creation date of this annotation.
      */
     protected String created;
@@ -155,6 +160,20 @@
     }
 
     /**
+     * @return the creatorName
+     */
+    public String getCreatorName() {
+        return creatorName;
+    }
+
+    /**
+     * @param creatorName the creatorName to set
+     */
+    public void setCreatorName(String creatorName) {
+        this.creatorName = creatorName;
+    }
+
+    /**
      * @return the created
      */
     public String getCreated() {
--- a/src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java	Mon Jul 02 22:39:46 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java	Tue Jul 03 21:23:17 2012 +0200
@@ -8,6 +8,7 @@
 import java.util.List;
 
 import org.apache.log4j.Logger;
+import org.neo4j.graphdb.Direction;
 import org.neo4j.graphdb.GraphDatabaseService;
 import org.neo4j.graphdb.Node;
 import org.neo4j.graphdb.Relationship;
@@ -58,9 +59,12 @@
         annot.setUri((String) annotNode.getProperty("id", null));
         annot.setBodyText((String) annotNode.getProperty("bodyText", null));
         annot.setBodyUri((String) annotNode.getProperty("bodyUri", null));
-        Iterable<Relationship> targets = annotNode.getRelationships(RelationTypes.ANNOTATES);
-        for (Relationship target : targets) {
+        // get annotation target from relation
+        Iterable<Relationship> targetRels = annotNode.getRelationships(RelationTypes.ANNOTATES);
+        for (Relationship targetRel : targetRels) {
+            Node target = targetRel.getEndNode();
             annot.setTargetBaseUri((String) target.getProperty("uri", null));
+            // just the first one
             break;
         }
         annot.setTargetFragment((String) annotNode.getProperty("targetFragment", null));
@@ -68,9 +72,13 @@
         if (ft != null) {
             annot.setFragmentType(FragmentTypes.valueOf(ft));
         }
-        Iterable<Relationship> creators = annotNode.getRelationships(RelationTypes.CREATED);
-        for (Relationship creator : creators) {
+        // get creator form relation
+        Iterable<Relationship> creatorRels = annotNode.getRelationships(RelationTypes.CREATED);
+        for (Relationship creatorRel : creatorRels) {
+            Node creator = creatorRel.getStartNode();
             annot.setCreatorUri((String) creator.getProperty("uri", null));
+            annot.setCreatorName((String) creator.getProperty("name", null));
+            // just the first one
             break;
         }
         annot.setCreated((String) annotNode.getProperty("created", null));
@@ -85,16 +93,18 @@
      * @return
      */
     public Annotation storeAnnotation(Annotation annot) {
+        Node annotNode = null;
         Transaction tx = graphDb.beginTx();
-        Node annotNode = null;
-        String id = annot.getUri();
-        if (id == null) {
-            id = createRessourceURI("annot:");
-        }
-        annotNode = createAnnotationNode(id);
+        try {
+            /*
+             * create or get the annotation
+             */
+            String id = annot.getUri();
+            if (id == null) {
+                id = createRessourceURI("annot:");
+            }
+            annotNode = getOrCreateAnnotationNode(id);
 
-        try {
-            // Mutating operations go here
             /*
              * the annotation body
              */
@@ -112,8 +122,8 @@
              */
             String targetBaseUri = annot.getTargetBaseUri();
             if (targetBaseUri != null) {
-                Node target = createTargetNode(targetBaseUri);
-                annotNode.createRelationshipTo(target, RelationTypes.ANNOTATES);
+                Node target = getOrCreateTargetNode(targetBaseUri);
+                getOrCreateRelation(annotNode, RelationTypes.ANNOTATES, target);
             }
 
             /*
@@ -127,12 +137,17 @@
             }
 
             /*
+             * The name of the creator of this annotation.
+             */
+            String creatorName = annot.getCreatorName();
+
+            /*
              * The URI of the creator of this annotation.
              */
             String creatorUri = annot.getCreatorUri();
             if (creatorUri != null) {
-                Node creator = createPersonNode(creatorUri, null);
-                creator.createRelationshipTo(annotNode, RelationTypes.CREATED);
+                Node creator = getOrCreatePersonNode(creatorUri, creatorName);
+                getOrCreateRelation(creator, RelationTypes.CREATED, annotNode);
             }
 
             /*
@@ -180,13 +195,13 @@
             Node target = targetIdx.get("uri", targetUri).getSingle();
             if (target != null) {
                 Iterable<Relationship> relations = target.getRelationships(RelationTypes.ANNOTATES);
-                for (Relationship relation: relations) {
+                for (Relationship relation : relations) {
                     Node ann = relation.getStartNode();
                     if (ann.getProperty("TYPE", "").equals("ANNOTATION")) {
                         Annotation annot = createAnnotation(ann);
                         annotations.add(annot);
                     } else {
-                        logger.error("ANNOTATES relation does not start with ANNOTATION: "+ann);
+                        logger.error("ANNOTATES relation does not start with ANNOTATION: " + ann);
                     }
                 }
             }
@@ -197,13 +212,13 @@
             Node person = persIdx.get("uri", userUri).getSingle();
             if (person != null) {
                 Iterable<Relationship> relations = person.getRelationships(RelationTypes.CREATED);
-                for (Relationship relation: relations) {
+                for (Relationship relation : relations) {
                     Node ann = relation.getEndNode();
                     if (ann.getProperty("TYPE", "").equals("ANNOTATION")) {
                         Annotation annot = createAnnotation(ann);
                         annotations.add(annot);
                     } else {
-                        logger.error("CREATED relation does not end with ANNOTATION: "+ann);
+                        logger.error("CREATED relation does not end with ANNOTATION: " + ann);
                     }
                 }
             }
@@ -211,7 +226,30 @@
         return annotations;
     }
 
-    protected Node createAnnotationNode(String id) {
+    protected Relationship getOrCreateRelation(Node start, RelationshipType type, Node end) {
+        if (start.hasRelationship()) {
+            // there are relations
+            Iterable<Relationship> rels = start.getRelationships(type, Direction.OUTGOING);
+            for (Relationship rel : rels) {
+                if (rel.getEndNode().equals(end)) {
+                    // relation exists
+                    return rel;
+                }
+            }
+        }
+        // create new one
+        Relationship rel;
+        Transaction tx = graphDb.beginTx();
+        try {
+            rel = start.createRelationshipTo(end, type);
+            tx.success();
+        } finally {
+            tx.finish();
+        }
+        return rel;
+    }
+
+    protected Node getOrCreateAnnotationNode(String id) {
         Index<Node> idx = graphDb.index().forNodes("annotations");
         IndexHits<Node> annotations = idx.get("id", id);
         Node annotation = annotations.getSingle();
@@ -231,7 +269,7 @@
         return annotation;
     }
 
-    protected Node createTargetNode(String uri) {
+    protected Node getOrCreateTargetNode(String uri) {
         Index<Node> idx = graphDb.index().forNodes("targets");
         IndexHits<Node> targets = idx.get("uri", uri);
         Node target = targets.getSingle();
@@ -251,7 +289,7 @@
         return target;
     }
 
-    protected Node createPersonNode(String uri, String name) {
+    protected Node getOrCreatePersonNode(String uri, String name) {
         Index<Node> idx = graphDb.index().forNodes("persons");
         // Person is identified by URI
         IndexHits<Node> persons = idx.get("uri", uri);
@@ -290,5 +328,4 @@
 
     }
 
-
 }
--- a/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java	Mon Jul 02 22:39:46 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java	Tue Jul 03 21:23:17 2012 +0200
@@ -8,7 +8,9 @@
 import java.net.URLEncoder;
 import java.security.InvalidKeyException;
 import java.security.SignatureException;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -177,6 +179,7 @@
      * @return
      */
     public JSONObject createAnnotatorJson(Annotation annot) {
+        // return user as a JSON object (otherwise just as string)
         boolean makeUserObject = true;
         JSONObject jo = new JSONObject();
         try {
@@ -197,8 +200,11 @@
                 // save as id
                 userObject.put("id", userId);
                 // get full name
-                RestServer restServer = (RestServer) getApplication();
-                String userName = restServer.getUserNameFromLdap(userId);
+                String userName = annot.getCreatorName();
+                if (userName == null) {
+                    RestServer restServer = (RestServer) getApplication();
+                    userName = restServer.getFullNameFromLdap(userId);
+                }
                 userObject.put("name", userName);
                 // save user object
                 jo.put("user", userObject);
@@ -240,7 +246,8 @@
 
         try {
             for (String xpointer : xpointers) {
-                String decoded = URLDecoder.decode(xpointer, "utf-8");
+                //String decoded = URLDecoder.decode(xpointer, "utf-8");
+                String decoded = xpointer;
                 Matcher m = rg.matcher(decoded);
 
                 if (m.find()) {
@@ -265,11 +272,7 @@
         } catch (JSONException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
-        } catch (UnsupportedEncodingException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
         }
-
         return ja;
     }
 
@@ -281,7 +284,8 @@
 
         try {
             for (String xpointer : xpointers) {
-                String decoded = URLDecoder.decode(xpointer, "utf-8");
+                //String decoded = URLDecoder.decode(xpointer, "utf-8");
+                String decoded = xpointer;
                 Matcher m = rg.matcher(decoded);
 
                 if (m.find()) {
@@ -299,15 +303,11 @@
         } catch (JSONException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
-        } catch (UnsupportedEncodingException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
         }
-
         return ja;
     }
 
-    protected String parseArea(JSONObject area) throws JSONException, UnsupportedEncodingException {
+    protected String parseArea(JSONObject area) throws JSONException {
         String x = area.getString("x");
         String y = area.getString("y");
         String width = "0";
@@ -316,24 +316,24 @@
             width = area.getString("width");
             height = area.getString("height");
         }
-        String fragment = URLEncoder.encode(String.format("xywh=fraction:%s,%s,%s,%s", x, y, width, height), "utf-8");
+        String fragment = String.format("xywh=fraction:%s,%s,%s,%s", x, y, width, height);
         return fragment;
     }
 
-    protected String parseRange(JSONObject range) throws JSONException, UnsupportedEncodingException {
+    protected String parseRange(JSONObject range) throws JSONException {
         String start = range.getString("start");
         String end = range.getString("end");
         String startOffset = range.getString("startOffset");
         String endOffset = range.getString("endOffset");
 
-        String fragment = URLEncoder.encode(String.format(
+        String fragment = 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");
+                startOffset, end, endOffset);
         return fragment;
     }
 
     /**
-     * creates an Annotation object with data from JSON.
+     * Creates an Annotation object with data from JSON.
      * 
      * uses the specification from the annotator project: {@link https
      * ://github.com/okfn/annotator/wiki/Annotation-format}
@@ -351,9 +351,25 @@
         return updateAnnotation(new Annotation(), jo, entity);
     }
 
+    /**
+     * Updates an Annotation object with data from JSON.
+     * 
+     * uses the specification from the annotator project: {@link https
+     * ://github.com/okfn/annotator/wiki/Annotation-format}
+     * 
+     * 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 annot
+     * @param jo
+     * @return
+     * @throws JSONException
+     * @throws UnsupportedEncodingException
+     */
     public Annotation updateAnnotation(Annotation annot, JSONObject jo, Representation entity) throws JSONException,
             UnsupportedEncodingException {
-        // annotated uri
+        // target uri
         if (jo.has("uri")) {
             annot.setTargetBaseUri(jo.getString("uri"));
         }
@@ -396,9 +412,13 @@
         if (username == null) {
             username = authUser;
         }
-        // username should be a URI, if not it will set to the MPIWG namespace
-        // defined in
-        // de.mpiwg.itgroup.annotationManager.Constants.NS
+        // try to get full name
+        if (username != null) {
+            RestServer restServer = (RestServer) getApplication();
+            String fullName = restServer.getFullNameFromLdap(username);
+            annot.setCreatorName(fullName);
+        }
+        // userUri should be a URI, if not it will set to the MPIWG namespace
         if (userUri == null) {
             if (username.startsWith("http")) {
                 userUri = username;
@@ -407,6 +427,16 @@
             }
         }
         // TODO: should we overwrite the creator?
+        if (annot.getCreatorUri() == null) {
+            annot.setCreatorUri(userUri);
+        }
+        
+        if (annot.getCreated() == null) {
+            // set creation date
+            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+            String ct = format.format(Calendar.getInstance().getTime());
+            annot.setCreated(ct);
+        }
 
         // create xpointer from the first range/area
         if (jo.has("ranges")) {
--- a/src/main/java/de/mpiwg/itgroup/annotations/restlet/RestServer.java	Mon Jul 02 22:39:46 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/restlet/RestServer.java	Tue Jul 03 21:23:17 2012 +0200
@@ -40,9 +40,13 @@
     private Properties consumerKeys;
     public String CONSUMER_KEYS_PATH = "WEB-INF/consumerkeys.property";
 
+    private Properties serverConfig;
+    public String CONFIG_PROPS_PATH = "WEB-INF/serverconfig.property";
+
     private GraphDatabaseService graphDb;
     public static final String GRAPHDB_KEY = "annotationmanager.graphdb";
-    public String DB_PATH = "WEB-INF/neo4j-annotation-db";
+    public static final String GRAPHDB_PATH_KEY = "annotationmanager.graphdb.path";
+    public String graphdbPath = "WEB-INF/neo4j-annotation-db";
 
     private WrappingNeoServerBootstrapper srv;
     public static final String GRAPHDBSRV_KEY = "annotationmanager.graphdb.srv";
@@ -63,13 +67,33 @@
         ServletContext sc = (ServletContext) getContext().getServerDispatcher().getContext().getAttributes()
                 .get("org.restlet.ext.servlet.ServletContext");
         if (sc != null) {
+            /*
+             * read config from webapp
+             */
+            serverConfig = new Properties();
+            InputStream ps1 = getResourceAsStream(sc, CONFIG_PROPS_PATH);
+            if (ps1 != null) {
+                logger.debug("loading config from " + CONFIG_PROPS_PATH);
+                try {
+                    serverConfig.load(ps1);
+                    /*
+                     * read serverconfig options
+                     */
+                    graphdbPath = serverConfig.getProperty(GRAPHDB_PATH_KEY, graphdbPath);
+                } catch (IOException e) {
+                    logger.warn("Error loading server config: ", e);
+                }
+                logger.debug("config: " + serverConfig);
+            } else {
+                logger.error("Unable to get resource " + CONFIG_PROPS_PATH);
+            }
             // look for database service in context
             graphDb = (GraphDatabaseService) sc.getAttribute(GRAPHDB_KEY);
             if (graphDb == null) {
                 /*
                  * open database
                  */
-                String dbFn = getResourcePath(sc, DB_PATH);
+                String dbFn = getResourcePath(sc, graphdbPath);
                 if (dbFn != null) {
                     logger.debug("opening DB " + dbFn);
                     graphDb = new GraphDatabaseFactory().newEmbeddedDatabase(dbFn);
@@ -86,18 +110,18 @@
                     sc.setAttribute(GRAPHDBSRV_KEY, srv);
                     srv.start();
                 } else {
-                    logger.error("Unable to get resource " + DB_PATH);
+                    logger.error("Unable to get resource " + dbFn);
                 }
             }
             /*
              * read consumerKeys from webapp
              */
             consumerKeys = new Properties();
-            InputStream ps = getResourceAsStream(sc, CONSUMER_KEYS_PATH);
-            if (ps != null) {
+            InputStream ps2 = getResourceAsStream(sc, CONSUMER_KEYS_PATH);
+            if (ps2 != null) {
                 logger.debug("loading consumer keys from " + CONSUMER_KEYS_PATH);
                 try {
-                    consumerKeys.load(ps);
+                    consumerKeys.load(ps2);
                 } catch (IOException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
@@ -154,7 +178,7 @@
      * @param creator
      * @return
      */
-    public String getUserNameFromLdap(String creator) {
+    public String getFullNameFromLdap(String creator) {
         String retString = creator; // falls nichts gefunden wird einfach den
                                     // creator zurueckgeben
         Hashtable<String, String> env = new Hashtable<String, String>();
@@ -162,7 +186,7 @@
         env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, sp);
 
         // TODO: should go into config file
-        String ldapUrl = "ldap://ldapreplik.mpiwg-berlin.mpg.de/dc=mpiwg-berlin,dc=mpg,dc=de"; 
+        String ldapUrl = "ldap://ldap.mpiwg-berlin.mpg.de/dc=mpiwg-berlin,dc=mpg,dc=de"; 
         env.put(javax.naming.Context.PROVIDER_URL, ldapUrl);
 
         DirContext dctx;
@@ -174,7 +198,7 @@
             return retString;
         }
 
-        String base = "ou=People";
+        String base = "ou=people";
 
         SearchControls sc = new SearchControls();
         String[] attributeFilter = { "cn", "mail" };