diff src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java @ 4:3599b29c393f

store seems to work now :-)
author casties
date Mon, 02 Jul 2012 22:39:46 +0200
parents
children bbf0cc5bee29
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java	Mon Jul 02 22:39:46 2012 +0200
@@ -0,0 +1,294 @@
+/**
+ * 
+ */
+package de.mpiwg.itgroup.annotations.neo4j;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.neo4j.graphdb.GraphDatabaseService;
+import org.neo4j.graphdb.Node;
+import org.neo4j.graphdb.Relationship;
+import org.neo4j.graphdb.RelationshipType;
+import org.neo4j.graphdb.Transaction;
+import org.neo4j.graphdb.index.Index;
+import org.neo4j.graphdb.index.IndexHits;
+
+import de.mpiwg.itgroup.annotations.Annotation;
+import de.mpiwg.itgroup.annotations.Annotation.FragmentTypes;
+
+/**
+ * @author casties
+ * 
+ */
+public class AnnotationStore {
+
+    protected static Logger logger = Logger.getLogger(AnnotationStore.class);
+
+    protected GraphDatabaseService graphDb;
+
+    public static enum RelationTypes implements RelationshipType {
+        ANNOTATES, CREATED
+    }
+
+    public static String ANNOTATION_URI_BASE = "http://entities.mpiwg-berlin.mpg.de/annotations/";
+
+    public AnnotationStore(GraphDatabaseService graphDb) {
+        super();
+        this.graphDb = graphDb;
+    }
+
+    public Annotation getAnnotationById(String id) {
+        Index<Node> idx = graphDb.index().forNodes("annotations");
+        Node annotNode = idx.get("id", id).getSingle();
+        Annotation annot = createAnnotation(annotNode);
+        return annot;
+    }
+
+    /**
+     * Returns an Annotation object from an annotation-Node.
+     * 
+     * @param annotNode
+     * @return
+     */
+    public Annotation createAnnotation(Node annotNode) {
+        Annotation annot = new Annotation();
+        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) {
+            annot.setTargetBaseUri((String) target.getProperty("uri", null));
+            break;
+        }
+        annot.setTargetFragment((String) annotNode.getProperty("targetFragment", null));
+        String ft = (String) annotNode.getProperty("fragmentType", null);
+        if (ft != null) {
+            annot.setFragmentType(FragmentTypes.valueOf(ft));
+        }
+        Iterable<Relationship> creators = annotNode.getRelationships(RelationTypes.CREATED);
+        for (Relationship creator : creators) {
+            annot.setCreatorUri((String) creator.getProperty("uri", null));
+            break;
+        }
+        annot.setCreated((String) annotNode.getProperty("created", null));
+        return annot;
+    }
+
+    /**
+     * Store a new annotation in the store or update an existing one. Returns
+     * the stored annotation.
+     * 
+     * @param annot
+     * @return
+     */
+    public Annotation storeAnnotation(Annotation annot) {
+        Transaction tx = graphDb.beginTx();
+        Node annotNode = null;
+        String id = annot.getUri();
+        if (id == null) {
+            id = createRessourceURI("annot:");
+        }
+        annotNode = createAnnotationNode(id);
+
+        try {
+            // Mutating operations go here
+            /*
+             * the annotation body
+             */
+            String bodyText = annot.getBodyText();
+            if (bodyText != null) {
+                annotNode.setProperty("bodyText", bodyText);
+            }
+            String bodyUri = annot.getBodyUri();
+            if (bodyUri != null) {
+                annotNode.setProperty("bodyUri", bodyUri);
+            }
+
+            /*
+             * the annotation target
+             */
+            String targetBaseUri = annot.getTargetBaseUri();
+            if (targetBaseUri != null) {
+                Node target = createTargetNode(targetBaseUri);
+                annotNode.createRelationshipTo(target, RelationTypes.ANNOTATES);
+            }
+
+            /*
+             * The fragment part of the annotation target.
+             */
+            String targetFragment = annot.getTargetFragment();
+            FragmentTypes fragmentType = annot.getFragmentType();
+            if (targetFragment != null) {
+                annotNode.setProperty("targetFragment", targetFragment);
+                annotNode.setProperty("fragmentType", fragmentType.name());
+            }
+
+            /*
+             * 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);
+            }
+
+            /*
+             * The creation date of this annotation.
+             */
+            String created = annot.getCreated();
+            if (created != null) {
+                annotNode.setProperty("created", created);
+            }
+
+            tx.success();
+        } finally {
+            tx.finish();
+        }
+
+        // re-read and return annotation
+        Annotation storedAnnot = createAnnotation(annotNode);
+        return storedAnnot;
+    }
+
+    /**
+     * Deletes the annotation with the id.
+     * 
+     * @param id
+     */
+    public void deleteById(String id) {
+        // TODO Auto-generated method stub
+
+    }
+
+    /**
+     * Returns all annotations with the given uri and/or user.
+     * 
+     * @param uri
+     * @param userUri
+     * @param limit
+     * @param offset
+     * @return
+     */
+    public List<Annotation> searchByUriUser(String targetUri, String userUri, String limit, String offset) {
+        List<Annotation> annotations = new ArrayList<Annotation>();
+        if (targetUri != null) {
+            Index<Node> targetIdx = graphDb.index().forNodes("targets");
+            // there should be only one
+            Node target = targetIdx.get("uri", targetUri).getSingle();
+            if (target != null) {
+                Iterable<Relationship> relations = target.getRelationships(RelationTypes.ANNOTATES);
+                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);
+                    }
+                }
+            }
+        }
+        if (userUri != null) {
+            Index<Node> persIdx = graphDb.index().forNodes("persons");
+            // there should be only one
+            Node person = persIdx.get("uri", userUri).getSingle();
+            if (person != null) {
+                Iterable<Relationship> relations = person.getRelationships(RelationTypes.CREATED);
+                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);
+                    }
+                }
+            }
+        }
+        return annotations;
+    }
+
+    protected Node createAnnotationNode(String id) {
+        Index<Node> idx = graphDb.index().forNodes("annotations");
+        IndexHits<Node> annotations = idx.get("id", id);
+        Node annotation = annotations.getSingle();
+        if (annotation == null) {
+            // does not exist yet
+            Transaction tx = graphDb.beginTx();
+            try {
+                annotation = graphDb.createNode();
+                annotation.setProperty("TYPE", "ANNOTATION");
+                annotation.setProperty("id", id);
+                idx.add(annotation, "id", id);
+                tx.success();
+            } finally {
+                tx.finish();
+            }
+        }
+        return annotation;
+    }
+
+    protected Node createTargetNode(String uri) {
+        Index<Node> idx = graphDb.index().forNodes("targets");
+        IndexHits<Node> targets = idx.get("uri", uri);
+        Node target = targets.getSingle();
+        if (target == null) {
+            // does not exist yet
+            Transaction tx = graphDb.beginTx();
+            try {
+                target = graphDb.createNode();
+                target.setProperty("TYPE", "TARGET");
+                target.setProperty("uri", uri);
+                idx.add(target, "uri", uri);
+                tx.success();
+            } finally {
+                tx.finish();
+            }
+        }
+        return target;
+    }
+
+    protected Node createPersonNode(String uri, String name) {
+        Index<Node> idx = graphDb.index().forNodes("persons");
+        // Person is identified by URI
+        IndexHits<Node> persons = idx.get("uri", uri);
+        Node person = persons.getSingle();
+        if (person == null) {
+            // does not exist yet
+            Transaction tx = graphDb.beginTx();
+            try {
+                person = graphDb.createNode();
+                person.setProperty("TYPE", "PERSON");
+                person.setProperty("uri", uri);
+                idx.add(person, "uri", uri);
+                if (name != null) {
+                    person.setProperty("name", name);
+                }
+                tx.success();
+            } finally {
+                tx.finish();
+            }
+        }
+        return person;
+    }
+
+    /**
+     * Erzeuge eine urn aus der aktuellen Zeit in millis
+     * 
+     * @return
+     */
+    private String createRessourceURI(String prefix) {
+
+        Calendar cal = Calendar.getInstance();
+
+        long time = cal.getTimeInMillis();
+
+        return String.format("%s%s%s", ANNOTATION_URI_BASE, prefix, time);
+
+    }
+
+
+}