source: AnnotationManagerN4J/src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java @ 5:bbf0cc5bee29

Last change on this file since 5:bbf0cc5bee29 was 5:bbf0cc5bee29, checked in by casties, 12 years ago

version 0.2 really works now

File size: 11.0 KB
Line 
1/**
2 *
3 */
4package de.mpiwg.itgroup.annotations.neo4j;
5
6import java.util.ArrayList;
7import java.util.Calendar;
8import java.util.List;
9
10import org.apache.log4j.Logger;
11import org.neo4j.graphdb.Direction;
12import org.neo4j.graphdb.GraphDatabaseService;
13import org.neo4j.graphdb.Node;
14import org.neo4j.graphdb.Relationship;
15import org.neo4j.graphdb.RelationshipType;
16import org.neo4j.graphdb.Transaction;
17import org.neo4j.graphdb.index.Index;
18import org.neo4j.graphdb.index.IndexHits;
19
20import de.mpiwg.itgroup.annotations.Annotation;
21import de.mpiwg.itgroup.annotations.Annotation.FragmentTypes;
22
23/**
24 * @author casties
25 *
26 */
27public class AnnotationStore {
28
29    protected static Logger logger = Logger.getLogger(AnnotationStore.class);
30
31    protected GraphDatabaseService graphDb;
32
33    public static enum RelationTypes implements RelationshipType {
34        ANNOTATES, CREATED
35    }
36
37    public static String ANNOTATION_URI_BASE = "http://entities.mpiwg-berlin.mpg.de/annotations/";
38
39    public AnnotationStore(GraphDatabaseService graphDb) {
40        super();
41        this.graphDb = graphDb;
42    }
43
44    public Annotation getAnnotationById(String id) {
45        Index<Node> idx = graphDb.index().forNodes("annotations");
46        Node annotNode = idx.get("id", id).getSingle();
47        Annotation annot = createAnnotation(annotNode);
48        return annot;
49    }
50
51    /**
52     * Returns an Annotation object from an annotation-Node.
53     *
54     * @param annotNode
55     * @return
56     */
57    public Annotation createAnnotation(Node annotNode) {
58        Annotation annot = new Annotation();
59        annot.setUri((String) annotNode.getProperty("id", null));
60        annot.setBodyText((String) annotNode.getProperty("bodyText", null));
61        annot.setBodyUri((String) annotNode.getProperty("bodyUri", null));
62        // get annotation target from relation
63        Iterable<Relationship> targetRels = annotNode.getRelationships(RelationTypes.ANNOTATES);
64        for (Relationship targetRel : targetRels) {
65            Node target = targetRel.getEndNode();
66            annot.setTargetBaseUri((String) target.getProperty("uri", null));
67            // just the first one
68            break;
69        }
70        annot.setTargetFragment((String) annotNode.getProperty("targetFragment", null));
71        String ft = (String) annotNode.getProperty("fragmentType", null);
72        if (ft != null) {
73            annot.setFragmentType(FragmentTypes.valueOf(ft));
74        }
75        // get creator form relation
76        Iterable<Relationship> creatorRels = annotNode.getRelationships(RelationTypes.CREATED);
77        for (Relationship creatorRel : creatorRels) {
78            Node creator = creatorRel.getStartNode();
79            annot.setCreatorUri((String) creator.getProperty("uri", null));
80            annot.setCreatorName((String) creator.getProperty("name", null));
81            // just the first one
82            break;
83        }
84        annot.setCreated((String) annotNode.getProperty("created", null));
85        return annot;
86    }
87
88    /**
89     * Store a new annotation in the store or update an existing one. Returns
90     * the stored annotation.
91     *
92     * @param annot
93     * @return
94     */
95    public Annotation storeAnnotation(Annotation annot) {
96        Node annotNode = null;
97        Transaction tx = graphDb.beginTx();
98        try {
99            /*
100             * create or get the annotation
101             */
102            String id = annot.getUri();
103            if (id == null) {
104                id = createRessourceURI("annot:");
105            }
106            annotNode = getOrCreateAnnotationNode(id);
107
108            /*
109             * the annotation body
110             */
111            String bodyText = annot.getBodyText();
112            if (bodyText != null) {
113                annotNode.setProperty("bodyText", bodyText);
114            }
115            String bodyUri = annot.getBodyUri();
116            if (bodyUri != null) {
117                annotNode.setProperty("bodyUri", bodyUri);
118            }
119
120            /*
121             * the annotation target
122             */
123            String targetBaseUri = annot.getTargetBaseUri();
124            if (targetBaseUri != null) {
125                Node target = getOrCreateTargetNode(targetBaseUri);
126                getOrCreateRelation(annotNode, RelationTypes.ANNOTATES, target);
127            }
128
129            /*
130             * The fragment part of the annotation target.
131             */
132            String targetFragment = annot.getTargetFragment();
133            FragmentTypes fragmentType = annot.getFragmentType();
134            if (targetFragment != null) {
135                annotNode.setProperty("targetFragment", targetFragment);
136                annotNode.setProperty("fragmentType", fragmentType.name());
137            }
138
139            /*
140             * The name of the creator of this annotation.
141             */
142            String creatorName = annot.getCreatorName();
143
144            /*
145             * The URI of the creator of this annotation.
146             */
147            String creatorUri = annot.getCreatorUri();
148            if (creatorUri != null) {
149                Node creator = getOrCreatePersonNode(creatorUri, creatorName);
150                getOrCreateRelation(creator, RelationTypes.CREATED, annotNode);
151            }
152
153            /*
154             * The creation date of this annotation.
155             */
156            String created = annot.getCreated();
157            if (created != null) {
158                annotNode.setProperty("created", created);
159            }
160
161            tx.success();
162        } finally {
163            tx.finish();
164        }
165
166        // re-read and return annotation
167        Annotation storedAnnot = createAnnotation(annotNode);
168        return storedAnnot;
169    }
170
171    /**
172     * Deletes the annotation with the id.
173     *
174     * @param id
175     */
176    public void deleteById(String id) {
177        // TODO Auto-generated method stub
178
179    }
180
181    /**
182     * Returns all annotations with the given uri and/or user.
183     *
184     * @param uri
185     * @param userUri
186     * @param limit
187     * @param offset
188     * @return
189     */
190    public List<Annotation> searchByUriUser(String targetUri, String userUri, String limit, String offset) {
191        List<Annotation> annotations = new ArrayList<Annotation>();
192        if (targetUri != null) {
193            Index<Node> targetIdx = graphDb.index().forNodes("targets");
194            // there should be only one
195            Node target = targetIdx.get("uri", targetUri).getSingle();
196            if (target != null) {
197                Iterable<Relationship> relations = target.getRelationships(RelationTypes.ANNOTATES);
198                for (Relationship relation : relations) {
199                    Node ann = relation.getStartNode();
200                    if (ann.getProperty("TYPE", "").equals("ANNOTATION")) {
201                        Annotation annot = createAnnotation(ann);
202                        annotations.add(annot);
203                    } else {
204                        logger.error("ANNOTATES relation does not start with ANNOTATION: " + ann);
205                    }
206                }
207            }
208        }
209        if (userUri != null) {
210            Index<Node> persIdx = graphDb.index().forNodes("persons");
211            // there should be only one
212            Node person = persIdx.get("uri", userUri).getSingle();
213            if (person != null) {
214                Iterable<Relationship> relations = person.getRelationships(RelationTypes.CREATED);
215                for (Relationship relation : relations) {
216                    Node ann = relation.getEndNode();
217                    if (ann.getProperty("TYPE", "").equals("ANNOTATION")) {
218                        Annotation annot = createAnnotation(ann);
219                        annotations.add(annot);
220                    } else {
221                        logger.error("CREATED relation does not end with ANNOTATION: " + ann);
222                    }
223                }
224            }
225        }
226        return annotations;
227    }
228
229    protected Relationship getOrCreateRelation(Node start, RelationshipType type, Node end) {
230        if (start.hasRelationship()) {
231            // there are relations
232            Iterable<Relationship> rels = start.getRelationships(type, Direction.OUTGOING);
233            for (Relationship rel : rels) {
234                if (rel.getEndNode().equals(end)) {
235                    // relation exists
236                    return rel;
237                }
238            }
239        }
240        // create new one
241        Relationship rel;
242        Transaction tx = graphDb.beginTx();
243        try {
244            rel = start.createRelationshipTo(end, type);
245            tx.success();
246        } finally {
247            tx.finish();
248        }
249        return rel;
250    }
251
252    protected Node getOrCreateAnnotationNode(String id) {
253        Index<Node> idx = graphDb.index().forNodes("annotations");
254        IndexHits<Node> annotations = idx.get("id", id);
255        Node annotation = annotations.getSingle();
256        if (annotation == null) {
257            // does not exist yet
258            Transaction tx = graphDb.beginTx();
259            try {
260                annotation = graphDb.createNode();
261                annotation.setProperty("TYPE", "ANNOTATION");
262                annotation.setProperty("id", id);
263                idx.add(annotation, "id", id);
264                tx.success();
265            } finally {
266                tx.finish();
267            }
268        }
269        return annotation;
270    }
271
272    protected Node getOrCreateTargetNode(String uri) {
273        Index<Node> idx = graphDb.index().forNodes("targets");
274        IndexHits<Node> targets = idx.get("uri", uri);
275        Node target = targets.getSingle();
276        if (target == null) {
277            // does not exist yet
278            Transaction tx = graphDb.beginTx();
279            try {
280                target = graphDb.createNode();
281                target.setProperty("TYPE", "TARGET");
282                target.setProperty("uri", uri);
283                idx.add(target, "uri", uri);
284                tx.success();
285            } finally {
286                tx.finish();
287            }
288        }
289        return target;
290    }
291
292    protected Node getOrCreatePersonNode(String uri, String name) {
293        Index<Node> idx = graphDb.index().forNodes("persons");
294        // Person is identified by URI
295        IndexHits<Node> persons = idx.get("uri", uri);
296        Node person = persons.getSingle();
297        if (person == null) {
298            // does not exist yet
299            Transaction tx = graphDb.beginTx();
300            try {
301                person = graphDb.createNode();
302                person.setProperty("TYPE", "PERSON");
303                person.setProperty("uri", uri);
304                idx.add(person, "uri", uri);
305                if (name != null) {
306                    person.setProperty("name", name);
307                }
308                tx.success();
309            } finally {
310                tx.finish();
311            }
312        }
313        return person;
314    }
315
316    /**
317     * Erzeuge eine urn aus der aktuellen Zeit in millis
318     *
319     * @return
320     */
321    private String createRessourceURI(String prefix) {
322
323        Calendar cal = Calendar.getInstance();
324
325        long time = cal.getTimeInMillis();
326
327        return String.format("%s%s%s", ANNOTATION_URI_BASE, prefix, time);
328
329    }
330
331}
Note: See TracBrowser for help on using the repository browser.