Changeset 14:629e15b345aa in AnnotationManagerN4J for src


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.

Location:
src/main/java/de/mpiwg/itgroup/annotations
Files:
6 edited

Legend:

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

    r13 r14  
    88/**
    99 * @author casties
    10  *
     10 * 
    1111 */
    1212public abstract class Actor {
     
    1515    public String name;
    1616    public String id;
    17    
     17
    1818    /**
    1919     * @return if this Actor is a Group
    2020     */
    2121    public abstract boolean isGroup();
    22    
     22
     23    /**
     24     * Returns if this Actor is equivalent to an Actor with this id. If this is
     25     * a Group returns true when the Person is in the Group.
     26     *
     27     * @param userId
     28     * @return
     29     */
     30    public boolean isEquivalentWith(String userId) {
     31        if (userId == null) return false;
     32        if (userId.equals(getIdString())) {
     33            return true;
     34        }
     35        if (isGroup()) {
     36            // TODO: check if person in group
     37        }
     38        return false;
     39    }
     40
    2341    /**
    2442     * @return the uri
     
    3452     */
    3553    public String getUriString() {
    36         if (uri == null) {
    37                 return getUriFromId(id, isGroup());
    38         }
     54        if (uri == null) {
     55            return getUriFromId(id, isGroup());
     56        }
    3957        return uri;
    4058    }
    4159
    4260    /**
    43      * @param uri the uri to set
     61     * @param uri
     62     *            the uri to set
    4463     */
    4564    public void setUri(String uri) {
    4665        this.uri = uri;
    4766    }
     67
    4868    /**
    4969     * @return the name
     
    5272        return name;
    5373    }
     74
    5475    /**
    55      * @param name the name to set
     76     * @param name
     77     *            the name to set
    5678     */
    5779    public void setName(String name) {
     
    6587        return id;
    6688    }
    67    
     89
    6890    /**
    6991     * Returns id as a String starting with "group:" for groups.
     
    7294     */
    7395    public abstract String getIdString();
    74    
     96
    7597    /**
    76      * @param id the id to set
     98     * @param id
     99     *            the id to set
    77100     */
    78101    public void setId(String id) {
    79102        this.id = id;
    80103    }
    81    
     104
    82105    /**
    83106     * Returns a short id from an uri.
     
    110133            prefix = NS.MPIWG_GROUPS_URL;
    111134        }
    112         if (id != null && ! id.startsWith("http://")) {
    113             uri = prefix + id; 
     135        if (id != null && !id.startsWith("http://")) {
     136            uri = prefix + id;
    114137        }
    115138        return uri;
  • src/main/java/de/mpiwg/itgroup/annotations/Annotation.java

    r10 r14  
    8181    protected Actor readPermission;
    8282   
     83   
     84    /**
     85     * Returns if the requested action is allowed on this annotation.
     86     *
     87     * @param action
     88     * @param userId
     89     * @return
     90     */
     91    public boolean isActionAllowed(String action, String userId) {
     92        if (action.equals("read")) {
     93            Actor reader = getReadPermission();
     94            if (reader == null) {
     95                return true;
     96            } else {
     97                return reader.isEquivalentWith(userId);
     98            }
     99        } else if (action.equals("update")) {
     100            // require at least an authenticated user
     101            if (userId == null) return false;
     102            Actor updater = getUpdatePermission();
     103            if (updater == null) {
     104                return true;
     105            } else {
     106                return updater.isEquivalentWith(userId);
     107            }
     108        } else if (action.equals("delete")) {
     109            // require at least an authenticated user
     110            if (userId == null) return false;
     111            Actor updater = getUpdatePermission();
     112            if (updater == null) {
     113                return true;
     114            } else {
     115                return updater.isEquivalentWith(userId);
     116            }
     117        } else if (action.equals("admin")) {
     118            // require at least an authenticated user
     119            if (userId == null) return false;
     120            Actor admin = getAdminPermission();
     121            if (admin == null) {
     122                return true;
     123            } else {
     124                return admin.isEquivalentWith(userId);
     125            }
     126        }
     127        return false;
     128    }
     129   
    83130    /**
    84131     * @return the uri
  • 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}
  • src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorAnnotations.java

    r4 r14  
    5151        // TODO: what to return without id - list of all annotations?
    5252
    53         // TODO: what to do with authentication?
    54         boolean authenticated = isAuthenticated(entity);
    55         logger.debug("request authenticated=" + authenticated);
    56 
    57         Annotation annots = getAnnotationStore().getAnnotationById(id);
    58         if (annots != null) {
    59             // there should be only one
    60             JSONObject result = createAnnotatorJson(annots);
     53        // do authentication
     54        String authUser = this.checkAuthToken(entity);
     55        logger.debug("request authenticated=" + authUser);
     56
     57        Annotation annot = getAnnotationStore().getAnnotationById(id);
     58        if (annot != null) {
     59            if (! annot.isActionAllowed("read", authUser)) {
     60                setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
     61                return null;
     62            }
     63            JSONObject result = createAnnotatorJson(annot, (authUser == null));
    6164            logger.debug("sending:");
    6265            logger.debug(result);
    6366            return new JsonRepresentation(result);
    6467        } else {
    65             JSONArray results = new JSONArray();
    66             // annotator read request returns a list of annotation objects
    67             logger.debug("sending:");
    68             logger.debug(results);
    69             return new JsonRepresentation(results);
     68            // not found
     69            setStatus(Status.CLIENT_ERROR_NOT_FOUND);
     70            return null;
    7071        }
    7172    }
     
    7374    /**
    7475     * POST with JSON content-type.
    75      *
    76      * json hash: username: name des users xpointer: xpointer auf den Ausschnitt
    77      * (incl. der URL des Dokumentes) text: text der annotation annoturl: url
    78      * auf eine Annotation falls extern
    7976     *
    8077     * @return
     
    8582        // set headers
    8683        setCorsHeaders();
     84       
     85        // do authentication TODO: who's allowed to create?
     86        String authUser = this.checkAuthToken(entity);
     87        logger.debug("request authenticated=" + authUser);
     88        if (authUser == null) {
     89            setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
     90            return null;
     91        }
     92
    8793        Annotation annot = null;
    8894        try {
     
    115121         * return 303: see other. For now we return the annotation.
    116122         */
    117         JSONObject jo = createAnnotatorJson(storedAnnot);
     123        JSONObject jo = createAnnotatorJson(storedAnnot, (authUser == null));
    118124        JsonRepresentation retRep = new JsonRepresentation(jo);
    119125        return retRep;
     
    135141        logger.debug("annotation-id=" + id);
    136142
    137         // TODO: what to do with authentication? we should check the owner
    138         boolean authenticated = isAuthenticated(entity);
    139         logger.debug("request authenticated=" + authenticated);
    140         if (!authenticated) {
    141             setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
    142             return null;
    143         }
     143        // do authentication
     144        String authUser = this.checkAuthToken(entity);
     145        logger.debug("request authenticated=" + authUser);
    144146
    145147        Annotation annot = null;
     
    156158            if (storedAnnot == null) {
    157159                setStatus(Status.CLIENT_ERROR_NOT_FOUND);
     160                return null;
     161            }
     162            if (! storedAnnot.isActionAllowed("update", authUser)) {
     163                setStatus(Status.CLIENT_ERROR_FORBIDDEN);
    158164                return null;
    159165            }
     
    170176             */
    171177            // return new annotation
    172             jo = createAnnotatorJson(storedAnnot);
     178            jo = createAnnotatorJson(storedAnnot, (authUser == null));
    173179            JsonRepresentation retRep = new JsonRepresentation(jo);
    174180            return retRep;
     
    198204        logger.debug("annotation-id=" + id);
    199205
    200         // TODO: what to do with authentication? we should check the owner
    201         boolean authenticated = isAuthenticated(entity);
    202         logger.debug("request authenticated=" + authenticated);
    203         if (!authenticated) {
    204             setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
    205             return null;
    206         }
    207 
     206        // do authentication
     207        String authUser = this.checkAuthToken(entity);
     208        logger.debug("request authenticated=" + authUser);
     209        Annotation annot = getAnnotationStore().getAnnotationById(id);
     210        if (annot != null) {
     211            if (! annot.isActionAllowed("delete", authUser)) {
     212                setStatus(Status.CLIENT_ERROR_FORBIDDEN, "Not Authorized!");
     213                return null;
     214            }
     215        }
     216       
    208217        // delete annotation
    209218        getAnnotationStore().deleteById(id);
  • src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java

    r10 r14  
    141141        Form requestHeaders = (Form) getRequest().getAttributes().get("org.restlet.http.headers");
    142142        String authToken = requestHeaders.getFirstValue("x-annotator-auth-token", true);
     143        if (authToken == null) return null;
    143144        // decode token first to get consumer key
    144145        JsonToken token = new JsonTokenParser(null, null).deserialize(authToken);
     
    178179     *
    179180     * @param annot
     181     * @param forAnonymous TODO
    180182     * @return
    181183     */
    182     public JSONObject createAnnotatorJson(Annotation annot) {
     184    public JSONObject createAnnotatorJson(Annotation annot, boolean forAnonymous) {
    183185        // return user as a JSON object (otherwise just as string)
    184186        boolean makeUserObject = true;
     
    233235            if (adminPerm != null) {
    234236                adminPerms.put(adminPerm.getIdString());
     237            } else if (forAnonymous) {
     238                // set something because its not allowed for anonymous
     239                adminPerms.put("not-you");
    235240            }
    236241            // delete
     
    240245            if (deletePerm != null) {
    241246                deletePerms.put(deletePerm.getIdString());
     247            } else if (forAnonymous) {
     248                // set something because its not allowed for anonymous
     249                deletePerms.put("not-you");
    242250            }
    243251            // update
     
    247255            if (updatePerm != null) {
    248256                updatePerms.put(updatePerm.getIdString());
     257            } else if (forAnonymous) {
     258                // set something because its not allowed for anonymous
     259                updatePerms.put("not-you");
    249260            }
    250261            // read
  • src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorSearch.java

    r4 r14  
    1616
    1717import de.mpiwg.itgroup.annotations.Annotation;
    18 import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore;
    1918
    2019/**
     
    3231
    3332    /**
    34      * result for JSON content-type. optional search parameters: uri user limit
    35      * offset
     33     * result for JSON content-type. optional search parameters: uri, user, limit,
     34     * offset.
    3635     *
    3736     * @param entity
     
    4241        logger.debug("AnnotatorSearch doGetJSON!");
    4342        setCorsHeaders();
    44         // TODO: what to do with authentication?
    45         boolean authenticated = isAuthenticated(entity);
    46         logger.debug("request authenticated=" + authenticated);
     43        // do authentication
     44        String authUser = this.checkAuthToken(entity);
     45        logger.debug("request authenticated=" + authUser);
    4746
    4847        Form form = getRequest().getResourceRef().getQueryAsForm();
    4948        String uri = form.getFirstValue("uri");
    5049        String user = form.getFirstValue("user");
    51 
    5250        String limit = form.getFirstValue("limit");
    5351        String offset = form.getFirstValue("offset");
    5452
    55         AnnotationStore searcher = getAnnotationStore();
    56 
    57         JSONArray ja;
    58 
    59         List<Annotation> annots = searcher.searchByUriUser(uri, user, limit, offset);
    60 
    61         ja = new JSONArray();
     53        JSONArray results = new JSONArray();
     54        // do search
     55        logger.debug(String.format("searching for uri=%s user=%s", uri, user));
     56        List<Annotation> annots = getAnnotationStore().searchByUriUser(uri, user, limit, offset);
    6257        for (Annotation annot : annots) {
    63             JSONObject jo = createAnnotatorJson(annot);
     58            // check permission
     59            if (!annot.isActionAllowed("read", authUser)) continue;
     60            JSONObject jo = createAnnotatorJson(annot, (authUser == null));
    6461            if (jo != null) {
    65                 ja.put(createAnnotatorJson(annot));
     62                results.put(jo);
    6663            } else {
    6764                setStatus(Status.SERVER_ERROR_INTERNAL, "JSON Error");
     
    6966            }
    7067        }
    71 
     68        // assemble result object
    7269        JSONObject result = new JSONObject();
    7370        try {
    74             result.put("rows", ja);
    75             result.put("total", ja.length());
     71            result.put("rows", results);
     72            result.put("total", results.length());
    7673        } catch (JSONException e) {
    77             e.printStackTrace();
    7874            setStatus(Status.SERVER_ERROR_INTERNAL, "JSON Error");
    7975            return null;
Note: See TracChangeset for help on using the changeset viewer.