changeset 22:b1fb0d117877

adding and listing groups via html works now. no editing of group membership yet. no authentication yet.
author casties
date Thu, 20 Sep 2012 17:42:26 +0200
parents 1ac626309352
children d22d01ba953a
files src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotationStoreGroups.java src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotationStoreRestlet.java src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorAnnotations.java src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java src/main/java/de/mpiwg/itgroup/annotations/restlet/BaseRestlet.java src/main/webapp/groups/index.html src/main/webapp/groups/new_group.html src/main/webapp/index.html
diffstat 9 files changed, 223 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java	Fri Sep 07 18:10:18 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java	Thu Sep 20 17:42:26 2012 +0200
@@ -140,6 +140,53 @@
     }
 
     /**
+     * Returns the members of the group.
+     * 
+     * @param group
+     * @return
+     */
+    public List<Person> getMembersOfGroup(Group group) {
+        ArrayList<Person> members = new ArrayList<Person>();
+        Node gn = getActorNode(group);
+        Iterable<Relationship> rels = gn.getRelationships(RelationTypes.MEMBER_OF);
+        for (Relationship rel : rels) {
+            Node memberNode = rel.getStartNode();
+            Actor member = createActorFromNode(memberNode);
+            // make sure we're getting a group
+            if (!(member instanceof Person)) {
+                logger.error("source of MEMBER_OF is not PERSON! rel=" + rel);
+                continue;
+            }
+            members.add((Person) member);
+        }
+        return members;
+    }
+    
+    /**
+     * Returns the stored Actor matching the given one.
+     * 
+     * @param actor
+     * @return
+     */
+    public Actor getActor(Actor actor) {
+    	Node actorNode = getActorNode(actor);
+    	Actor storedActor = createActorFromNode(actorNode);
+    	return storedActor;
+    }
+    
+    /**
+     * Stores an Actor (Person or Group). Creates a new actor Node or returns an existing one.
+     * 
+     * @param actor
+     * @return
+     */
+    public Actor storeActor(Actor actor) {
+    	Node actorNode = getOrCreateActorNode(actor);
+    	Actor storedActor = createActorFromNode(actorNode);
+    	return storedActor;
+    }
+    
+    /**
      * Returns the Annotation with the given id.
      * 
      * @param id
@@ -535,6 +582,20 @@
         return target;
     }
 
+    protected Node getActorNode(Actor actor) {
+        // Person/Group is identified by URI or id
+        String uri = actor.getUriString();
+        Index<Node> idx;
+        if (actor.isGroup()) {
+            idx = getNodeIndex(NodeTypes.GROUP);
+        } else {
+            idx = getNodeIndex(NodeTypes.PERSON);
+        }
+        IndexHits<Node> persons = idx.get("uri", uri);
+        Node person = persons.getSingle();
+        return person;
+    }
+    
     protected Node getOrCreateActorNode(Actor actor) {
         // Person/Group is identified by URI or id
         String uri = actor.getUriString();
--- a/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotationStoreGroups.java	Fri Sep 07 18:10:18 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotationStoreGroups.java	Thu Sep 20 17:42:26 2012 +0200
@@ -5,22 +5,25 @@
 
 import java.util.List;
 
-import javax.servlet.ServletContext;
-
 import org.apache.log4j.Logger;
 import org.restlet.data.Form;
 import org.restlet.data.MediaType;
+import org.restlet.data.Reference;
+import org.restlet.data.Status;
 import org.restlet.representation.Representation;
 import org.restlet.representation.StringRepresentation;
 import org.restlet.resource.Get;
+import org.restlet.resource.Post;
 import org.restlet.resource.ServerResource;
 
+import de.mpiwg.itgroup.annotations.Actor;
 import de.mpiwg.itgroup.annotations.Group;
+import de.mpiwg.itgroup.annotations.Person;
 import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore;
 
 /**
  * @author casties
- *
+ * 
  */
 public class AnnotationStoreGroups extends ServerResource {
 
@@ -28,35 +31,98 @@
 
     private AnnotationStore store;
 
+    /**
+     * GET with HTML content type. Lists all groups.
+     * 
+     * @param entity
+     * @return
+     */
     @Get("html")
-    public Representation doGetHTML(Representation entity){
-        Form form = getRequest().getResourceRef().getQueryAsForm();
+    public Representation doGetHTML(Representation entity) {
         // id from URI /annotations/groups/{id}
         String id = (String) getRequest().getAttributes().get("id");
         logger.debug("group-id=" + id);
-        String result="<html><body>\n<h1>Groups</h1>\n<table>";
-        result += "<tr><th>id</th><th>name</th><th>uri</th></tr>";
+        String result = null;
         store = getAnnotationStore();
         if (id == null) {
             // list all groups
-            List<Group> groups = store.getGroups("uri", "*");
-            for (Group group : groups) {
-                String groupLink = group.getId();
-                result += String.format("<tr><td><a href=\"%s\">%s</a></td><td>%s</td><td>%s</td></tr>\n", groupLink, group.getId(), group.getName(), group.getUri());
-            }
-        } else {
-            // just one group
+            result = "<html><body>\n<h1>Groups</h1>\n<table>";
+            result += "<tr><th>id</th><th>name</th><th>uri</th></tr>";
             List<Group> groups = store.getGroups("uri", "*");
             for (Group group : groups) {
-                String groupLink = group.getId();
-                result += String.format("<tr><td><a href=\"%s\">%s</a></td><td>%s</td><td>%s</td></tr>\n", groupLink, group.getId(), group.getName(), group.getUri());
+                Reference groupUrl = this.getReference();
+                groupUrl.addSegment(group.getId());
+                result += String.format("<tr><td><a href=\"%s\">%s</a></td><td>%s</td><td>%s</td></tr>\n", groupUrl,
+                        group.getId(), group.getName(), group.getUri());
             }
+            result += "</table>\n</body>\n</html>";
+        } else {
+            // just one group
+            Reference groupsUrl = this.getReference().getParentRef();
+            result = "<html><body>\n<h1>Group</h1>\n";
+            result += String.format("<p><a href=\"%s\">All groups</a></p>", groupsUrl);
+            Group group = new Group(id);
+            group = (Group) store.getActor(group);
+            result += "<table>";
+            result += String.format("<tr><td><b>id</b></td><td>%s</td></tr>\n", group.getId());
+            result += String.format("<tr><td><b>name</b></td><td>%s</td></tr>\n", group.getName());
+            result += String.format("<tr><td><b>uri</b></td><td>%s</td></tr>\n", group.getUri());
+            result += "<tr><td><b>members</b></td><td>";
+            List<Person> members = store.getMembersOfGroup(group);
+            for (Person p : members) {
+                result += String.format("%s (%s)\n", p.getName(), p.getIdString());                
+            }
+            result += "</td></tr>\n";
+            result += "</table>\n</body>\n</html>";
         }
-        result += "</table>\n</body>\n</html>";
-        
+
         logger.debug("sending:");
         logger.debug(result);
-        return new StringRepresentation(result,MediaType.TEXT_HTML);
+        return new StringRepresentation(result, MediaType.TEXT_HTML);
+    }
+
+    /**
+     * POST with HTML content-type. Creates a new Group.
+     * 
+     * @return
+     */
+    @Post
+    public Representation doPostHTML(Representation entity) {
+        logger.debug("AnnotationStoreGroups doPostHTML!");
+        // TODO: do authentication
+        Form form = new Form(entity);
+        String id = form.getFirstValue("id");
+        String name = form.getFirstValue("name");
+        if (id == null || id.isEmpty()) {
+            // invalid id
+            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
+            return null;
+        }
+        String gid = makeGroupId(id);
+        Group newGroup = new Group(gid, null, name);
+        store = getAnnotationStore();
+        Actor storedGroup = store.storeActor(newGroup);
+        gid = storedGroup.getId();
+        // return 303: see other
+        setStatus(Status.REDIRECTION_SEE_OTHER);
+        // go GET URL for this group
+        Reference groupUrl = this.getReference();
+        groupUrl.addSegment(gid);
+        this.getResponse().setLocationRef(groupUrl);
+        return null;
+    }
+
+    /**
+     * Returns a group id based on the given id.
+     * 
+     * @param id
+     * @return
+     */
+    protected String makeGroupId(String id) {
+        // TODO: should we use different ids?
+        id = id.replaceAll("\\W", "_");
+        id = id.toLowerCase();
+        return id;
     }
 
     protected AnnotationStore getAnnotationStore() {
--- a/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotationStoreRestlet.java	Fri Sep 07 18:10:18 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotationStoreRestlet.java	Thu Sep 20 17:42:26 2012 +0200
@@ -35,6 +35,7 @@
         Router router = new Router(getContext());
 
         router.attach("/groups", AnnotationStoreGroups.class);
+        router.attach("/groups/", AnnotationStoreGroups.class);
         router.attach("/groups/{id}", AnnotationStoreGroups.class);
 
         router.attach("/", AnnotationStoreInfo.class);
--- a/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorAnnotations.java	Fri Sep 07 18:10:18 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorAnnotations.java	Thu Sep 20 17:42:26 2012 +0200
@@ -48,7 +48,11 @@
         String id = decodeJsonId(jsonId);
         logger.debug("annotation-id=" + id);
 
-        // TODO: what to return without id - list of all annotations?
+        if (id == null) {
+            // TODO: what to return without id - list all annotations?
+            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
+            return null;
+        }
 
         // do authentication
         Person authUser = Person.createPersonWithId(this.checkAuthToken(entity));
--- a/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java	Fri Sep 07 18:10:18 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java	Thu Sep 20 17:42:26 2012 +0200
@@ -65,6 +65,7 @@
     }
 
     public String encodeJsonId(String id) {
+        if (id == null) return null;
         try {
             return Base64.encodeBase64URLSafeString(id.getBytes("UTF-8"));
         } catch (UnsupportedEncodingException e) {
@@ -73,6 +74,7 @@
     }
 
     public String decodeJsonId(String id) {
+        if (id == null) return null;
         try {
             return new String(Base64.decodeBase64(id), "UTF-8");
         } catch (UnsupportedEncodingException e) {
--- a/src/main/java/de/mpiwg/itgroup/annotations/restlet/BaseRestlet.java	Fri Sep 07 18:10:18 2012 +0200
+++ b/src/main/java/de/mpiwg/itgroup/annotations/restlet/BaseRestlet.java	Thu Sep 20 17:42:26 2012 +0200
@@ -134,6 +134,9 @@
                 } else {
                     logger.error("Unable to get resource " + dbFn);
                 }
+            } else {
+                // get existing AnnotationStore
+                store = (AnnotationStore) sc.getAttribute(ANNSTORE_KEY);
             }
             /*
              * read consumerKeys from webapp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/webapp/groups/index.html	Thu Sep 20 17:42:26 2012 +0200
@@ -0,0 +1,20 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+<title>Annotation Server Groups</title>
+
+</head>
+
+<body>
+	<h1>Annotation groups</h1>
+	<ul>
+		<li><a href="../annotations/groups">List groups</a></li>
+		<li><a href="new_group.html">Add new group</a></li>
+	</ul>
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/webapp/groups/new_group.html	Thu Sep 20 17:42:26 2012 +0200
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+<title>Annotation Server Groups</title>
+
+</head>
+
+<body>
+  <h1>New group</h1>
+  <form action="../annotations/groups" method="post">
+    <table>
+      <tr>
+        <td>ID (short name)</td>
+        <td><input name="id" type="text" /></td>
+      </tr>
+      <tr>
+        <td>Name</td>
+        <td><input name="name" type="text" /></td>
+      </tr>
+    </table>
+    <input type="submit"/>
+  </form>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/webapp/index.html	Thu Sep 20 17:42:26 2012 +0200
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+<title>Annotation Server</title>
+
+</head>
+
+<body>
+	<h1>Annotation Server</h1>
+	<ul>
+		<li><a href="groups">View and edit groups</a></li>
+	</ul>
+</body>
+</html>