Ignore:
Timestamp:
Jul 13, 2012, 6:41:02 PM (12 years ago)
Author:
casties
Branch:
default
Message:

permissions mostly work. need more server-side checking.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/main/java/de/mpiwg/itgroup/annotations/neo4j/AnnotationStore.java

    r13 r14  
    3030public class AnnotationStore {
    3131
    32         protected static Logger logger = Logger.getLogger(AnnotationStore.class);
    33 
    34         protected GraphDatabaseService graphDb;
    35 
    36         public static enum NodeTypes {
    37                 ANNOTATION, PERSON, TARGET
    38         }
    39 
    40         protected List<Index<Node>> nodeIndexes;
    41 
    42         public static enum RelationTypes implements RelationshipType {
    43                 ANNOTATES, CREATED, PERMITS_ADMIN, PERMITS_DELETE, PERMITS_UPDATE, PERMITS_READ
    44         }
    45 
    46         public static String ANNOTATION_URI_BASE = "http://entities.mpiwg-berlin.mpg.de/annotations/";
    47 
    48         public AnnotationStore(GraphDatabaseService graphDb) {
    49                 super();
    50                 this.graphDb = graphDb;
    51                 nodeIndexes = new ArrayList<Index<Node>>(3);
    52                 // List.set(enum.ordinal(), val) seems not to work.
    53                 nodeIndexes.add(NodeTypes.ANNOTATION.ordinal(), graphDb.index()
    54                                 .forNodes("annotations"));
    55                 nodeIndexes.add(NodeTypes.PERSON.ordinal(),
    56                                 graphDb.index().forNodes("persons"));
    57                 nodeIndexes.add(NodeTypes.TARGET.ordinal(),
    58                                 graphDb.index().forNodes("targets"));
    59         }
    60 
    61         protected Index<Node> getNodeIndex(NodeTypes type) {
    62                 return nodeIndexes.get(type.ordinal());
    63         }
    64 
    65         /**
    66          * Returns the Annotation with the given id.
    67          *
    68          * @param id
    69          * @return
    70          */
    71         public Annotation getAnnotationById(String id) {
    72                 Node annotNode = getNodeIndex(NodeTypes.ANNOTATION).get("id", id)
    73                                 .getSingle();
    74                 Annotation annot = createAnnotationFromNode(annotNode);
    75                 return annot;
    76         }
    77 
    78         /**
    79          * Returns an Annotation object from an annotation-Node.
    80          *
    81          * @param annotNode
    82          * @return
    83          */
    84         public Annotation createAnnotationFromNode(Node annotNode) {
    85                 Annotation annot = new Annotation();
    86                 annot.setUri((String) annotNode.getProperty("id", null));
    87                 annot.setBodyText((String) annotNode.getProperty("bodyText", null));
    88                 annot.setBodyUri((String) annotNode.getProperty("bodyUri", null));
    89                 // get annotation target from relation
    90                 Relationship targetRel = getRelation(annotNode,
    91                                 RelationTypes.ANNOTATES, null);
    92                 if (targetRel != null) {
    93                         Node target = targetRel.getEndNode();
    94                         annot.setTargetBaseUri((String) target.getProperty("uri", null));
    95                 } else {
    96                         logger.error("annotation " + annotNode + " has no target node!");
    97                 }
    98                 annot.setTargetFragment((String) annotNode.getProperty(
    99                                 "targetFragment", null));
    100                 String ft = (String) annotNode.getProperty("fragmentType", null);
    101                 if (ft != null) {
    102                         annot.setFragmentType(FragmentTypes.valueOf(ft));
    103                 }
    104                 // get creator from relation
    105                 Relationship creatorRel = getRelation(annotNode, RelationTypes.CREATED,
    106                                 null);
    107                 if (creatorRel != null) {
    108                         Node creatorNode = creatorRel.getStartNode();
    109                         Actor creator = createActorFromNode(creatorNode);
    110                         annot.setCreator(creator);
    111                 } else {
    112                         logger.error("annotation " + annotNode + " has no creator node!");
    113                 }
    114                 // get creation date
    115                 annot.setCreated((String) annotNode.getProperty("created", null));
    116                 // get permissions
    117                 Relationship adminRel = getRelation(annotNode,
    118                                 RelationTypes.PERMITS_ADMIN, null);
    119                 if (adminRel != null) {
    120                         Node adminNode = adminRel.getEndNode();
    121                         Actor admin = createActorFromNode(adminNode);
    122                         annot.setAdminPermission(admin);
    123                 }
    124                 Relationship deleteRel = getRelation(annotNode,
    125                                 RelationTypes.PERMITS_DELETE, null);
    126                 if (deleteRel != null) {
    127                         Node deleteNode = deleteRel.getEndNode();
    128                         Actor delete = createActorFromNode(deleteNode);
    129                         annot.setDeletePermission(delete);
    130                 }
    131                 Relationship updateRel = getRelation(annotNode,
    132                                 RelationTypes.PERMITS_UPDATE, null);
    133                 if (updateRel != null) {
    134                         Node updateNode = updateRel.getEndNode();
    135                         Actor update = createActorFromNode(updateNode);
    136                         annot.setUpdatePermission(update);
    137                 }
    138                 Relationship readRel = getRelation(annotNode,
    139                                 RelationTypes.PERMITS_READ, null);
    140                 if (readRel != null) {
    141                         Node readNode = readRel.getEndNode();
    142                         Actor read = createActorFromNode(readNode);
    143                         annot.setReadPermission(read);
    144                 }
    145 
    146                 return annot;
    147         }
    148 
    149         /**
    150          * Returns an Actor object from a node.
    151          *
    152          * @param actorNode
    153          * @return
    154          */
    155         protected Actor createActorFromNode(Node actorNode) {
    156                 String uri = (String) actorNode.getProperty("uri", null);
    157                 String name = (String) actorNode.getProperty("name", null);
    158                 String type = (String) actorNode.getProperty("TYPE", null);
    159                 if (type != null && type.equals("PERSON")) {
    160                         return new Person(uri, name);
    161                 } else if (type != null && type.equals("GROUP")) {
    162                         return new Group(uri, name);
    163                 }
    164                 return null;
    165         }
    166 
    167         /**
    168          * Store a new annotation in the store or update an existing one. Returns
    169          * the stored annotation.
    170          *
    171          * @param annot
    172          * @return
    173          */
    174         public Annotation storeAnnotation(Annotation annot) {
    175                 Node annotNode = null;
    176                 Transaction tx = graphDb.beginTx();
    177                 try {
    178                         /*
    179                          * create or get the annotation
    180                          */
    181                         String id = annot.getUri();
    182                         if (id == null) {
    183                                 id = createRessourceURI("annot:");
    184                         }
    185                         annotNode = getOrCreateAnnotationNode(id);
    186 
    187                         /*
    188                          * the annotation body
    189                          */
    190                         String bodyText = annot.getBodyText();
    191                         if (bodyText != null) {
    192                                 annotNode.setProperty("bodyText", bodyText);
    193                         }
    194                         String bodyUri = annot.getBodyUri();
    195                         if (bodyUri != null) {
    196                                 annotNode.setProperty("bodyUri", bodyUri);
    197                         }
    198 
    199                         /*
    200                          * the annotation target
    201                          */
    202                         String targetBaseUri = annot.getTargetBaseUri();
    203                         if (targetBaseUri != null) {
    204                                 Node target = getOrCreateTargetNode(targetBaseUri);
    205                                 getOrCreateRelation(annotNode, RelationTypes.ANNOTATES, target);
    206                         }
    207 
    208                         /*
    209                          * The fragment part of the annotation target.
    210                          */
    211                         String targetFragment = annot.getTargetFragment();
    212                         FragmentTypes fragmentType = annot.getFragmentType();
    213                         if (targetFragment != null) {
    214                                 annotNode.setProperty("targetFragment", targetFragment);
    215                                 annotNode.setProperty("fragmentType", fragmentType.name());
    216                         }
    217 
    218                         /*
    219                          * The creator of this annotation.
    220                          */
    221                         Actor creator = annot.getCreator();
    222                         if (creator != null) {
    223                                 Node creatorNode = getOrCreatePersonNode(creator);
    224                                 getOrCreateRelation(creatorNode, RelationTypes.CREATED,
    225                                                 annotNode);
    226                         }
    227 
    228                         /*
    229                          * The creation date of this annotation.
    230                          */
    231                         String created = annot.getCreated();
    232                         if (created != null) {
    233                                 annotNode.setProperty("created", created);
    234                         }
    235 
    236                         /*
    237                          * Permissions for this annotation.
    238                          */
    239                         setPermissionRelation(annotNode, RelationTypes.PERMITS_ADMIN,
    240                                         annot.getAdminPermission());
    241                         setPermissionRelation(annotNode, RelationTypes.PERMITS_DELETE,
    242                                         annot.getDeletePermission());
    243                         setPermissionRelation(annotNode, RelationTypes.PERMITS_UPDATE,
    244                                         annot.getUpdatePermission());
    245                         setPermissionRelation(annotNode, RelationTypes.PERMITS_READ,
    246                                         annot.getReadPermission());
    247 
    248                         tx.success();
    249                 } finally {
    250                         tx.finish();
    251                 }
    252 
    253                 // re-read and return annotation
    254                 Annotation storedAnnot = createAnnotationFromNode(annotNode);
    255                 return storedAnnot;
    256         }
    257 
    258         /**
    259          * Deletes the annotation with the given id.
    260          *
    261          * @param id
    262          */
    263         public void deleteById(String id) {
    264                 Node annotNode = getNodeIndex(NodeTypes.ANNOTATION).get("id", id)
    265                                 .getSingle();
    266                 if (annotNode != null) {
    267                         // delete related objects
    268                         Transaction tx = graphDb.beginTx();
    269                         try {
    270                                 for (Relationship rel : annotNode.getRelationships()) {
    271                                         // delete relation and the related node if it has no other
    272                                         // relations
    273                                         Node other = rel.getOtherNode(annotNode);
    274                                         rel.delete();
    275                                         if (!other.hasRelationship()) {
    276                                                 deleteNode(other);
    277                                         }
    278                                 }
    279                                 if (!annotNode.hasRelationship()) {
    280                                         deleteNode(annotNode);
    281                                 } else {
    282                                         logger.error("deleteById: unable to delete: Node still has relations.");
    283                                 }
    284                                 tx.success();
    285                         } finally {
    286                                 tx.finish();
    287                         }
    288                 }
    289         }
    290 
    291         /**
    292          * Returns all annotations with the given uri and/or user.
    293          *
    294          * @param uri
    295          * @param userUri
    296          * @param limit
    297          * @param offset
    298          * @return
    299          */
    300         public List<Annotation> searchByUriUser(String targetUri, String userUri,
    301                         String limit, String offset) {
    302                 List<Annotation> annotations = new ArrayList<Annotation>();
    303                 if (targetUri != null) {
    304                         // there should be only one
    305                         Node target = getNodeIndex(NodeTypes.TARGET).get("uri", targetUri)
    306                                         .getSingle();
    307                         if (target != null) {
    308                                 Iterable<Relationship> relations = target
    309                                                 .getRelationships(RelationTypes.ANNOTATES);
    310                                 for (Relationship relation : relations) {
    311                                         Node ann = relation.getStartNode();
    312                                         if (ann.getProperty("TYPE", "").equals("ANNOTATION")) {
    313                                                 Annotation annot = createAnnotationFromNode(ann);
    314                                                 annotations.add(annot);
    315                                         } else {
    316                                                 logger.error("ANNOTATES relation does not start with ANNOTATION: "
    317                                                                 + ann);
    318                                         }
    319                                 }
    320                         }
    321                 }
    322                 if (userUri != null) {
    323                         // there should be only one
    324                         Node person = getNodeIndex(NodeTypes.PERSON).get("uri", userUri)
    325                                         .getSingle();
    326                         if (person != null) {
    327                                 Iterable<Relationship> relations = person
    328                                                 .getRelationships(RelationTypes.CREATED);
    329                                 for (Relationship relation : relations) {
    330                                         Node ann = relation.getEndNode();
    331                                         if (ann.getProperty("TYPE", "").equals("ANNOTATION")) {
    332                                                 Annotation annot = createAnnotationFromNode(ann);
    333                                                 annotations.add(annot);
    334                                         } else {
    335                                                 logger.error("CREATED relation does not end with ANNOTATION: "
    336                                                                 + ann);
    337                                         }
    338                                 }
    339                         }
    340                 }
    341                 return annotations;
    342         }
    343 
    344         protected Relationship getOrCreateRelation(Node start,
    345                         RelationshipType type, Node end) {
    346                 if (start.hasRelationship()) {
    347                         // there are relations
    348                         Iterable<Relationship> rels = start.getRelationships(type,
    349                                         Direction.OUTGOING);
    350                         for (Relationship rel : rels) {
    351                                 if (rel.getEndNode().equals(end)) {
    352                                         // relation exists
    353                                         return rel;
    354                                 }
    355                         }
    356                 }
    357                 // create new one
    358                 Relationship rel;
    359                 Transaction tx = graphDb.beginTx();
    360                 try {
    361                         rel = start.createRelationshipTo(end, type);
    362                         tx.success();
    363                 } finally {
    364                         tx.finish();
    365                 }
    366                 return rel;
    367         }
    368 
    369         protected Node getOrCreateAnnotationNode(String id) {
    370                 Index<Node> idx = getNodeIndex(NodeTypes.ANNOTATION);
    371                 IndexHits<Node> annotations = idx.get("id", id);
    372                 Node annotation = annotations.getSingle();
    373                 if (annotation == null) {
    374                         // does not exist yet
    375                         Transaction tx = graphDb.beginTx();
    376                         try {
    377                                 annotation = graphDb.createNode();
    378                                 annotation.setProperty("TYPE", NodeTypes.ANNOTATION.name());
    379                                 annotation.setProperty("id", id);
    380                                 idx.add(annotation, "id", id);
    381                                 tx.success();
    382                         } finally {
    383                                 tx.finish();
    384                         }
    385                 }
    386                 return annotation;
    387         }
    388 
    389         protected Node getOrCreateTargetNode(String uri) {
    390                 Index<Node> idx = getNodeIndex(NodeTypes.TARGET);
    391                 IndexHits<Node> targets = idx.get("uri", uri);
    392                 Node target = targets.getSingle();
    393                 if (target == null) {
    394                         // does not exist yet
    395                         Transaction tx = graphDb.beginTx();
    396                         try {
    397                                 target = graphDb.createNode();
    398                                 target.setProperty("TYPE", NodeTypes.TARGET.name());
    399                                 target.setProperty("uri", uri);
    400                                 idx.add(target, "uri", uri);
    401                                 tx.success();
    402                         } finally {
    403                                 tx.finish();
    404                         }
    405                 }
    406                 return target;
    407         }
    408 
    409         protected Node getOrCreatePersonNode(Actor actor) {
    410                 // Person is identified by URI
    411                 String uri = actor.getUriString();
    412                 String name = actor.getName();
    413                 Index<Node> idx = getNodeIndex(NodeTypes.PERSON);
    414                 IndexHits<Node> persons = idx.get("uri", uri);
    415                 Node person = persons.getSingle();
    416                 if (person == null) {
    417                         // does not exist yet
    418                         Transaction tx = graphDb.beginTx();
    419                         try {
    420                                 person = graphDb.createNode();
    421                                 person.setProperty("TYPE", NodeTypes.PERSON.name());
    422                                 person.setProperty("uri", uri);
    423                                 idx.add(person, "uri", uri);
    424                                 if (name != null) {
    425                                         person.setProperty("name", name);
    426                                 }
    427                                 tx.success();
    428                         } finally {
    429                                 tx.finish();
    430                         }
    431                 }
    432                 return person;
    433         }
    434 
    435         /**
    436          * Create or update permissions relations for an annotation.
    437          *
    438          * @param annotNode
    439          * @param type
    440          * @param annot
    441          */
    442         protected void setPermissionRelation(Node annotNode, RelationTypes type,
    443                         Actor actor) {
    444                 Node newActorNode = null;
    445                 if (actor != null) {
    446                         newActorNode = getOrCreatePersonNode(actor);
    447                 }
    448                 Relationship rel = getRelation(annotNode, type, null);
    449                 if (rel != null) {
    450                         // relation exists
    451                         Node oldActorNode = rel.getEndNode();
    452                         if (!oldActorNode.equals(newActorNode)) {
    453                                 // new admin is different
    454                                 rel.delete();
    455                                 if (newActorNode != null) {
    456                                         rel = getOrCreateRelation(annotNode, type, newActorNode);
    457                                 }
    458                         }
    459                 } else {
    460                         // no relation yet
    461                         if (newActorNode != null) {
    462                                 rel = getOrCreateRelation(annotNode, type, newActorNode);
    463                         }
    464                 }
    465         }
    466 
    467         /**
    468          * Unindexes and deletes given Node if it has no relations.
    469          *
    470          * @param node
    471          */
    472         protected void deleteNode(Node node) {
    473                 Transaction tx = graphDb.beginTx();
    474                 try {
    475                         if (node.hasRelationship()) {
    476                                 logger.error("deleteNode: unable to delete: Node still has relations.");
    477                         } else {
    478                                 String ts = (String) node.getProperty("TYPE", null);
    479                                 try {
    480                                         NodeTypes type = NodeTypes.valueOf(ts);
    481                                         getNodeIndex(type).remove(node);
    482                                 } catch (Exception e) {
    483                                         logger.error("deleteNode: unable to get TYPE of node: "
    484                                                         + node);
    485                                 }
    486                                 node.delete();
    487                         }
    488                         tx.success();
    489                 } finally {
    490                         tx.finish();
    491                 }
    492         }
    493 
    494         protected Relationship getRelation(Node start, RelationTypes type,
    495                         Direction direction) {
    496                 Iterable<Relationship> rels;
    497                 if (direction == null) {
    498                         // ignore direction
    499                         rels = start.getRelationships(type);
    500                 } else {
    501                         rels = start.getRelationships(type, direction);
    502                 }
    503                 for (Relationship rel : rels) {
    504                         return rel;
    505                 }
    506                 return null;
    507         }
    508 
    509         /**
    510          * Erzeuge eine urn aus der aktuellen Zeit in millis
    511          *
    512          * @return
    513          */
    514         private String createRessourceURI(String prefix) {
    515 
    516                 Calendar cal = Calendar.getInstance();
    517 
    518                 long time = cal.getTimeInMillis();
    519 
    520                 return String.format("%s%s%s", ANNOTATION_URI_BASE, prefix, time);
    521 
    522         }
     32    protected static Logger logger = Logger.getLogger(AnnotationStore.class);
     33
     34    protected GraphDatabaseService graphDb;
     35
     36    public static enum NodeTypes {
     37        ANNOTATION, PERSON, TARGET
     38    }
     39
     40    protected List<Index<Node>> nodeIndexes;
     41
     42    public static enum RelationTypes implements RelationshipType {
     43        ANNOTATES, CREATED, PERMITS_ADMIN, PERMITS_DELETE, PERMITS_UPDATE, PERMITS_READ
     44    }
     45
     46    public static String ANNOTATION_URI_BASE = "http://entities.mpiwg-berlin.mpg.de/annotations/";
     47
     48    public AnnotationStore(GraphDatabaseService graphDb) {
     49        super();
     50        this.graphDb = graphDb;
     51        nodeIndexes = new ArrayList<Index<Node>>(3);
     52        // List.set(enum.ordinal(), val) seems not to work.
     53        nodeIndexes.add(NodeTypes.ANNOTATION.ordinal(), graphDb.index().forNodes("annotations"));
     54        nodeIndexes.add(NodeTypes.PERSON.ordinal(), graphDb.index().forNodes("persons"));
     55        nodeIndexes.add(NodeTypes.TARGET.ordinal(), graphDb.index().forNodes("targets"));
     56    }
     57
     58    protected Index<Node> getNodeIndex(NodeTypes type) {
     59        return nodeIndexes.get(type.ordinal());
     60    }
     61
     62    /**
     63     * Returns the Annotation with the given id.
     64     *
     65     * @param id
     66     * @return
     67     */
     68    public Annotation getAnnotationById(String id) {
     69        Node annotNode = getNodeIndex(NodeTypes.ANNOTATION).get("id", id).getSingle();
     70        Annotation annot = createAnnotationFromNode(annotNode);
     71        return annot;
     72    }
     73
     74    /**
     75     * Returns an Annotation object from an annotation-Node.
     76     *
     77     * @param annotNode
     78     * @return
     79     */
     80    public Annotation createAnnotationFromNode(Node annotNode) {
     81        Annotation annot = new Annotation();
     82        annot.setUri((String) annotNode.getProperty("id", null));
     83        annot.setBodyText((String) annotNode.getProperty("bodyText", null));
     84        annot.setBodyUri((String) annotNode.getProperty("bodyUri", null));
     85        // get annotation target from relation
     86        Relationship targetRel = getRelation(annotNode, RelationTypes.ANNOTATES, null);
     87        if (targetRel != null) {
     88            Node target = targetRel.getEndNode();
     89            annot.setTargetBaseUri((String) target.getProperty("uri", null));
     90        } else {
     91            logger.error("annotation " + annotNode + " has no target node!");
     92        }
     93        annot.setTargetFragment((String) annotNode.getProperty("targetFragment", null));
     94        String ft = (String) annotNode.getProperty("fragmentType", null);
     95        if (ft != null) {
     96            annot.setFragmentType(FragmentTypes.valueOf(ft));
     97        }
     98        // get creator from relation
     99        Relationship creatorRel = getRelation(annotNode, RelationTypes.CREATED, null);
     100        if (creatorRel != null) {
     101            Node creatorNode = creatorRel.getStartNode();
     102            Actor creator = createActorFromNode(creatorNode);
     103            annot.setCreator(creator);
     104        } else {
     105            logger.error("annotation " + annotNode + " has no creator node!");
     106        }
     107        // get creation date
     108        annot.setCreated((String) annotNode.getProperty("created", null));
     109        // get permissions
     110        Relationship adminRel = getRelation(annotNode, RelationTypes.PERMITS_ADMIN, null);
     111        if (adminRel != null) {
     112            Node adminNode = adminRel.getEndNode();
     113            Actor admin = createActorFromNode(adminNode);
     114            annot.setAdminPermission(admin);
     115        }
     116        Relationship deleteRel = getRelation(annotNode, RelationTypes.PERMITS_DELETE, null);
     117        if (deleteRel != null) {
     118            Node deleteNode = deleteRel.getEndNode();
     119            Actor delete = createActorFromNode(deleteNode);
     120            annot.setDeletePermission(delete);
     121        }
     122        Relationship updateRel = getRelation(annotNode, RelationTypes.PERMITS_UPDATE, null);
     123        if (updateRel != null) {
     124            Node updateNode = updateRel.getEndNode();
     125            Actor update = createActorFromNode(updateNode);
     126            annot.setUpdatePermission(update);
     127        }
     128        Relationship readRel = getRelation(annotNode, RelationTypes.PERMITS_READ, null);
     129        if (readRel != null) {
     130            Node readNode = readRel.getEndNode();
     131            Actor read = createActorFromNode(readNode);
     132            annot.setReadPermission(read);
     133        }
     134
     135        return annot;
     136    }
     137
     138    /**
     139     * Returns an Actor object from a node.
     140     *
     141     * @param actorNode
     142     * @return
     143     */
     144    protected Actor createActorFromNode(Node actorNode) {
     145        String uri = (String) actorNode.getProperty("uri", null);
     146        String name = (String) actorNode.getProperty("name", null);
     147        String type = (String) actorNode.getProperty("TYPE", null);
     148        if (type != null && type.equals("PERSON")) {
     149            return new Person(uri, name);
     150        } else if (type != null && type.equals("GROUP")) {
     151            return new Group(uri, name);
     152        }
     153        return null;
     154    }
     155
     156    /**
     157     * Store a new annotation in the store or update an existing one. Returns
     158     * the stored annotation.
     159     *
     160     * @param annot
     161     * @return
     162     */
     163    public Annotation storeAnnotation(Annotation annot) {
     164        Node annotNode = null;
     165        Transaction tx = graphDb.beginTx();
     166        try {
     167            /*
     168             * create or get the annotation
     169             */
     170            String id = annot.getUri();
     171            if (id == null) {
     172                id = createRessourceURI("annot:");
     173            }
     174            annotNode = getOrCreateAnnotationNode(id);
     175
     176            /*
     177             * the annotation body
     178             */
     179            String bodyText = annot.getBodyText();
     180            if (bodyText != null) {
     181                annotNode.setProperty("bodyText", bodyText);
     182            }
     183            String bodyUri = annot.getBodyUri();
     184            if (bodyUri != null) {
     185                annotNode.setProperty("bodyUri", bodyUri);
     186            }
     187
     188            /*
     189             * the annotation target
     190             */
     191            String targetBaseUri = annot.getTargetBaseUri();
     192            if (targetBaseUri != null) {
     193                Node target = getOrCreateTargetNode(targetBaseUri);
     194                getOrCreateRelation(annotNode, RelationTypes.ANNOTATES, target);
     195            }
     196
     197            /*
     198             * The fragment part of the annotation target.
     199             */
     200            String targetFragment = annot.getTargetFragment();
     201            FragmentTypes fragmentType = annot.getFragmentType();
     202            if (targetFragment != null) {
     203                annotNode.setProperty("targetFragment", targetFragment);
     204                annotNode.setProperty("fragmentType", fragmentType.name());
     205            }
     206
     207            /*
     208             * The creator of this annotation.
     209             */
     210            Actor creator = annot.getCreator();
     211            if (creator != null) {
     212                Node creatorNode = getOrCreatePersonNode(creator);
     213                getOrCreateRelation(creatorNode, RelationTypes.CREATED, annotNode);
     214            }
     215
     216            /*
     217             * The creation date of this annotation.
     218             */
     219            String created = annot.getCreated();
     220            if (created != null) {
     221                annotNode.setProperty("created", created);
     222            }
     223
     224            /*
     225             * Permissions for this annotation.
     226             */
     227            setPermissionRelation(annotNode, RelationTypes.PERMITS_ADMIN, annot.getAdminPermission());
     228            setPermissionRelation(annotNode, RelationTypes.PERMITS_DELETE, annot.getDeletePermission());
     229            setPermissionRelation(annotNode, RelationTypes.PERMITS_UPDATE, annot.getUpdatePermission());
     230            setPermissionRelation(annotNode, RelationTypes.PERMITS_READ, annot.getReadPermission());
     231
     232            tx.success();
     233        } finally {
     234            tx.finish();
     235        }
     236
     237        // re-read and return annotation
     238        Annotation storedAnnot = createAnnotationFromNode(annotNode);
     239        return storedAnnot;
     240    }
     241
     242    /**
     243     * Deletes the annotation with the given id.
     244     *
     245     * @param id
     246     */
     247    public void deleteById(String id) {
     248        Node annotNode = getNodeIndex(NodeTypes.ANNOTATION).get("id", id).getSingle();
     249        if (annotNode != null) {
     250            // delete related objects
     251            Transaction tx = graphDb.beginTx();
     252            try {
     253                for (Relationship rel : annotNode.getRelationships()) {
     254                    // delete relation and the related node if it has no other
     255                    // relations
     256                    Node other = rel.getOtherNode(annotNode);
     257                    rel.delete();
     258                    if (!other.hasRelationship()) {
     259                        deleteNode(other);
     260                    }
     261                }
     262                if (!annotNode.hasRelationship()) {
     263                    deleteNode(annotNode);
     264                } else {
     265                    logger.error("deleteById: unable to delete: Node still has relations.");
     266                }
     267                tx.success();
     268            } finally {
     269                tx.finish();
     270            }
     271        }
     272    }
     273
     274    /**
     275     * Returns all annotations with the given uri and/or user.
     276     *
     277     * @param uri
     278     * @param userUri
     279     * @param limit
     280     * @param offset
     281     * @return
     282     */
     283    public List<Annotation> searchByUriUser(String targetUri, String userUri, String limit, String offset) {
     284        List<Annotation> annotations = new ArrayList<Annotation>();
     285        if (targetUri != null) {
     286            // there should be only one
     287            Node target = getNodeIndex(NodeTypes.TARGET).get("uri", targetUri).getSingle();
     288            if (target != null) {
     289                Iterable<Relationship> relations = target.getRelationships(RelationTypes.ANNOTATES);
     290                for (Relationship relation : relations) {
     291                    Node ann = relation.getStartNode();
     292                    if (ann.getProperty("TYPE", "").equals("ANNOTATION")) {
     293                        Annotation annot = createAnnotationFromNode(ann);
     294                        annotations.add(annot);
     295                    } else {
     296                        logger.error("ANNOTATES relation does not start with ANNOTATION: " + ann);
     297                    }
     298                }
     299            }
     300        }
     301        if (userUri != null) {
     302            // there should be only one
     303            Node person = getNodeIndex(NodeTypes.PERSON).get("uri", userUri).getSingle();
     304            if (person != null) {
     305                Iterable<Relationship> relations = person.getRelationships(RelationTypes.CREATED);
     306                for (Relationship relation : relations) {
     307                    Node ann = relation.getEndNode();
     308                    if (ann.getProperty("TYPE", "").equals("ANNOTATION")) {
     309                        Annotation annot = createAnnotationFromNode(ann);
     310                        annotations.add(annot);
     311                    } else {
     312                        logger.error("CREATED relation does not end with ANNOTATION: " + ann);
     313                    }
     314                }
     315            }
     316        }
     317        return annotations;
     318    }
     319
     320    protected Relationship getOrCreateRelation(Node start, RelationshipType type, Node end) {
     321        if (start.hasRelationship()) {
     322            // there are relations
     323            Iterable<Relationship> rels = start.getRelationships(type, Direction.OUTGOING);
     324            for (Relationship rel : rels) {
     325                if (rel.getEndNode().equals(end)) {
     326                    // relation exists
     327                    return rel;
     328                }
     329            }
     330        }
     331        // create new one
     332        Relationship rel;
     333        Transaction tx = graphDb.beginTx();
     334        try {
     335            rel = start.createRelationshipTo(end, type);
     336            tx.success();
     337        } finally {
     338            tx.finish();
     339        }
     340        return rel;
     341    }
     342
     343    protected Node getOrCreateAnnotationNode(String id) {
     344        Index<Node> idx = getNodeIndex(NodeTypes.ANNOTATION);
     345        IndexHits<Node> annotations = idx.get("id", id);
     346        Node annotation = annotations.getSingle();
     347        if (annotation == null) {
     348            // does not exist yet
     349            Transaction tx = graphDb.beginTx();
     350            try {
     351                annotation = graphDb.createNode();
     352                annotation.setProperty("TYPE", NodeTypes.ANNOTATION.name());
     353                annotation.setProperty("id", id);
     354                idx.add(annotation, "id", id);
     355                tx.success();
     356            } finally {
     357                tx.finish();
     358            }
     359        }
     360        return annotation;
     361    }
     362
     363    protected Node getOrCreateTargetNode(String uri) {
     364        Index<Node> idx = getNodeIndex(NodeTypes.TARGET);
     365        IndexHits<Node> targets = idx.get("uri", uri);
     366        Node target = targets.getSingle();
     367        if (target == null) {
     368            // does not exist yet
     369            Transaction tx = graphDb.beginTx();
     370            try {
     371                target = graphDb.createNode();
     372                target.setProperty("TYPE", NodeTypes.TARGET.name());
     373                target.setProperty("uri", uri);
     374                idx.add(target, "uri", uri);
     375                tx.success();
     376            } finally {
     377                tx.finish();
     378            }
     379        }
     380        return target;
     381    }
     382
     383    protected Node getOrCreatePersonNode(Actor actor) {
     384        // Person is identified by URI
     385        String uri = actor.getUriString();
     386        String name = actor.getName();
     387        Index<Node> idx = getNodeIndex(NodeTypes.PERSON);
     388        IndexHits<Node> persons = idx.get("uri", uri);
     389        Node person = persons.getSingle();
     390        if (person == null) {
     391            // does not exist yet
     392            Transaction tx = graphDb.beginTx();
     393            try {
     394                person = graphDb.createNode();
     395                person.setProperty("TYPE", NodeTypes.PERSON.name());
     396                person.setProperty("uri", uri);
     397                idx.add(person, "uri", uri);
     398                if (name != null) {
     399                    person.setProperty("name", name);
     400                }
     401                tx.success();
     402            } finally {
     403                tx.finish();
     404            }
     405        }
     406        return person;
     407    }
     408
     409    /**
     410     * Create or update permissions relations for an annotation.
     411     *
     412     * @param annotNode
     413     * @param type
     414     * @param annot
     415     */
     416    protected void setPermissionRelation(Node annotNode, RelationTypes type, Actor actor) {
     417        Node newActorNode = null;
     418        if (actor != null) {
     419            newActorNode = getOrCreatePersonNode(actor);
     420        }
     421        Relationship rel = getRelation(annotNode, type, null);
     422        if (rel != null) {
     423            // relation exists
     424            Node oldActorNode = rel.getEndNode();
     425            if (!oldActorNode.equals(newActorNode)) {
     426                // new admin is different
     427                rel.delete();
     428                if (newActorNode != null) {
     429                    rel = getOrCreateRelation(annotNode, type, newActorNode);
     430                }
     431            }
     432        } else {
     433            // no relation yet
     434            if (newActorNode != null) {
     435                rel = getOrCreateRelation(annotNode, type, newActorNode);
     436            }
     437        }
     438    }
     439
     440    /**
     441     * Unindexes and deletes given Node if it has no relations.
     442     *
     443     * @param node
     444     */
     445    protected void deleteNode(Node node) {
     446        Transaction tx = graphDb.beginTx();
     447        try {
     448            if (node.hasRelationship()) {
     449                logger.error("deleteNode: unable to delete: Node still has relations.");
     450            } else {
     451                String ts = (String) node.getProperty("TYPE", null);
     452                try {
     453                    NodeTypes type = NodeTypes.valueOf(ts);
     454                    getNodeIndex(type).remove(node);
     455                } catch (Exception e) {
     456                    logger.error("deleteNode: unable to get TYPE of node: " + node);
     457                }
     458                node.delete();
     459            }
     460            tx.success();
     461        } finally {
     462            tx.finish();
     463        }
     464    }
     465
     466    protected Relationship getRelation(Node start, RelationTypes type, Direction direction) {
     467        Iterable<Relationship> rels;
     468        if (direction == null) {
     469            // ignore direction
     470            rels = start.getRelationships(type);
     471        } else {
     472            rels = start.getRelationships(type, direction);
     473        }
     474        for (Relationship rel : rels) {
     475            return rel;
     476        }
     477        return null;
     478    }
     479
     480    /**
     481     * Erzeuge eine urn aus der aktuellen Zeit in millis
     482     *
     483     * @return
     484     */
     485    private String createRessourceURI(String prefix) {
     486
     487        Calendar cal = Calendar.getInstance();
     488
     489        long time = cal.getTimeInMillis();
     490
     491        return String.format("%s%s%s", ANNOTATION_URI_BASE, prefix, time);
     492
     493    }
    523494
    524495}
Note: See TracChangeset for help on using the changeset viewer.