def testAnnotate(self): """ Annotate file in created RO ro annotate file attribute-name [ attribute-value ] """ rodir = self.createTestRo("data/ro-test-1", "RO test annotation", "ro-testRoAnnotate") args = [ "ro", "annotate", rodir+"/"+"subdir1/subdir1-file.txt", "title", "subdir1-file title", "-v", ] with SwitchStdout(self.outstr): status = ro.runCommand(ro_test_config.CONFIGDIR, ro_test_config.ROBASEDIR, args) outtxt = self.outstr.getvalue() assert status == 0, outtxt self.assertEqual(outtxt.count("ro annotate"), 1) #self.assertRegexpMatches(outtxt, "annotation.*dc:title") # Read manifest and check for annotation manifestgraph = ro_manifest.readManifestGraph(rodir) filesubj = ro_manifest.getComponentUri(rodir, "subdir1/subdir1-file.txt") log.debug("filesubj %s"%filesubj) filetitle = manifestgraph.value(filesubj, DCTERMS.title, None), self.assertEqual(len(filetitle), 1, "Singleton result expected") self.assertEqual(filetitle[0], "subdir1-file title") self.deleteTestRo(rodir) return
def createAnnotationBody(ro_config, ro_dir, rofile, attrdict, defaultType="string"): """ Create a new annotation body for a single resource in a research object. Existing annotations for the same resource are not touched; if an annotation is being added or replaced, it is the calling program'sresponsibility to update the manifest to reference the active annotations. A new name is allocated for the created annotation, which is returned as the result of this function. ro_config is the research object manager configuration, supplied as a dictionary ro_dir is the research object root directory rofile is the name of the Research Object component to be annotated, possibly relative to the RO root directory. attrdict is a dictionary of attributes to be saved inthe annotation body. Dictionary keys are attribute names that can be resolved via getAnnotationByName. Returns the name of the annotation body created relative to the RO manifest and metadata directory. """ # Assemble data for annotation anngraph = rdflib.Graph() s = ro_manifest.getComponentUri(ro_dir, rofile) for k in attrdict: (p,t) = getAnnotationByName(ro_config, k, defaultType) anngraph.add((s, p, makeAnnotationValue(ro_config, attrdict[k],t))) # Write graph and return filename return createAnnotationGraphBody(ro_config, ro_dir, rofile, anngraph)
def _addAnnotationBodyToRoGraph(ro_graph, ro_dir, rofile, annfile): """ Add a new annotation body to an RO graph ro_graph graph to which annotation is added ro_dir is the research object directory rofile is the research object file being annotated annfile is the base file name of the annotation body to be added """ # <ore:aggregates> # <ro:AggregatedAnnotation> # <ro:annotatesAggregatedResource rdf:resource="data/UserRequirements-astro.ods" /> # <ao:body rdf:resource=".ro/(annotation).rdf" /> # </ro:AggregatedAnnotation> # </ore:aggregates> ann = rdflib.BNode() ro_graph.add((ann, RDF.type, RO.AggregatedAnnotation)) ro_graph.add((ann, RO.annotatesAggregatedResource, ro_manifest.getComponentUri(ro_dir, rofile))) ro_graph.add((ann, AO.body, ro_manifest.getComponentUri(ro_dir, ro_settings.MANIFEST_DIR+"/"+annfile))) ro_graph.add((ro_manifest.getComponentUri(ro_dir, "."), ORE.aggregates, ann)) return
def _getAnnotationValues(ro_config, ro_dir, rofile, attrname): """ Returns iterator over annotation values for given subject and attribute """ log.debug("getAnnotationValues: ro_dir %s, rofile %s, attrname %s"%(ro_dir, rofile, attrname)) ro_graph = ro_manifest.readManifestGraph(ro_dir) subject = ro_manifest.getComponentUri(ro_dir, rofile) (predicate,valtype) = getAnnotationByName(ro_config, attrname) #@@TODO refactor common code with getRoAnnotations, etc. for ann_node in ro_graph.subjects(predicate=RO.annotatesAggregatedResource, object=subject): ann_uri = ro_graph.value(subject=ann_node, predicate=AO.body) ann_graph = readAnnotationBody(ro_dir, ro_manifest.getComponentUriRel(ro_dir, ann_uri)) for v in ann_graph.objects(subject=subject, predicate=predicate): #log.debug("Triple: %s %s %s"%(subject,p,v)) yield v return
def _removeSimpleAnnotation(ro_config, ro_dir, rofile, attrname, attrvalue): """ Remove a simple annotation or multiple matching annotations a research object. ro_config is the research object manager configuration, supplied as a dictionary ro_dir is the research object root directory rofile names the annotated file or resource, possibly relative to the RO. attrname names the attribute in a form recognized by getAnnotationByName attrvalue is the attribute value to be deleted, or Nomne to delete all vaues """ log.debug("removeSimpleAnnotation: ro_dir %s, rofile %s, attrname %s, attrvalue %s"% (ro_dir, rofile, attrname, attrvalue)) # Enumerate annotations # For each: # if annotation is only one in graph then: # remove aggregated annotation # else: # create new annotation graph witj annotation removed # update aggregated annotation ro_graph = ro_manifest.readManifestGraph(ro_dir) subject = ro_manifest.getComponentUri(ro_dir, rofile) (predicate,valtype) = getAnnotationByName(ro_config, attrname) val = attrvalue and makeAnnotationValue(ro_config, attrvalue, valtype) #@@TODO refactor common code with getRoAnnotations, etc. add_annotations = [] remove_annotations = [] for ann_node in ro_graph.subjects(predicate=RO.annotatesAggregatedResource, object=subject): ann_uri = ro_graph.value(subject=ann_node, predicate=AO.body) ann_graph = readAnnotationBody(ro_dir, ro_manifest.getComponentUriRel(ro_dir, ann_uri)) if (subject, predicate, val) in ann_graph: ann_graph.remove((subject, predicate, val)) if (subject, None, None) in ann_graph: # Triples remain in annotation body: write new body and update RO graph ann_name = createAnnotationGraphBody(ro_config, ro_dir, rofile, ann_graph) remove_annotations.append(ann_node) add_annotations.append(ann_name) else: # Remove annotation from RO graph remove_annotations.append(ann_node) # Update RO graph if needed if add_annotations or remove_annotations: for a in remove_annotations: _removeAnnotationBodyFromRoGraph(ro_graph, a) for a in add_annotations: _addAnnotationBodyToRoGraph(ro_graph, ro_dir, rofile, a) ro_manifest.writeManifestGraph(ro_dir, ro_graph) return
def _replaceSimpleAnnotation(ro_config, ro_dir, rofile, attrname, attrvalue): """ Replace a simple annotation in a research object. ro_config is the research object manager configuration, supplied as a dictionary ro_dir is the research object root directory rofile names the file or resource to be annotated, possibly relative to the RO. attrname names the attribute in a form recognized by getAnnotationByName attrvalue is a new value to be associated with the attribute """ ro_graph = ro_manifest.readManifestGraph(ro_dir) subject = ro_manifest.getComponentUri(ro_dir, rofile) (predicate,valtype) = getAnnotationByName(ro_config, attrname) log.debug("Replace annotation: subject %s, predicate %s, value %s"%(repr(subject), repr(predicate), repr(attrvalue))) ro_graph.remove((subject, predicate, None)) ro_graph.add((subject, predicate, makeAnnotationValue(ro_config, attrvalue, valtype))) ro_manifest.writeManifestGraph(ro_dir, ro_graph) return
def _getFileAnnotations(ro_dir, rofile): """ Returns iterator over annotations applied to a specified component in the RO Each value returned by the iterator is a (subject,predicate,object) triple. """ log.debug("getFileAnnotations: ro_dir %s, rofile %s"%(ro_dir, rofile)) ro_graph = ro_manifest.readManifestGraph(ro_dir) subject = ro_manifest.getComponentUri(ro_dir, rofile) log.debug("getFileAnnotations: %s"%str(subject)) #@@TODO refactor common code with getRoAnnotations, etc. for ann_node in ro_graph.subjects(predicate=RO.annotatesAggregatedResource, object=subject): ann_uri = ro_graph.value(subject=ann_node, predicate=AO.body) ann_graph = readAnnotationBody(ro_dir, ro_manifest.getComponentUriRel(ro_dir, ann_uri)) if ann_graph: for (p, v) in ann_graph.predicate_objects(subject=subject): #log.debug("Triple: %s %s %s"%(subject,p,v)) yield (subject, p, v) return
def annotationTest(self, anntype, annvalue, anntypeuri, annexpect): rodir = self.createTestRo("data/ro-test-1", "RO test annotation", "ro-testRoAnnotate") args = [ "ro", "annotate", rodir+"/"+"subdir1/subdir1-file.txt", anntype, annvalue, "-v", ] with SwitchStdout(self.outstr): status = ro.runCommand(ro_test_config.CONFIGDIR, ro_test_config.ROBASEDIR, args) outtxt = self.outstr.getvalue() assert status == 0, outtxt self.assertEqual(outtxt.count("ro annotate"), 1) # Read manifest and check for annotation manifestgraph = ro_manifest.readManifestGraph(rodir) filesubj = ro_manifest.getComponentUri(rodir, "subdir1/subdir1-file.txt") fileann = manifestgraph.value(filesubj, anntypeuri, None), #@@TODO: deal with case that expected result is a list self.assertEqual(len(fileann), 1, "Singleton result expected") self.assertEqual(fileann[0], annexpect) self.deleteTestRo(rodir) return
def annotations(progname, configbase, options, args): """ Dusplay annotations ro annotations [ file | -d dir ] """ # Check command arguments if len(args) not in [2,3]: print ("%s annotations: wrong number of arguments provided"% (progname)) print ("Usage: %s annotations [ file | -d dir ]"% (progname)) return 1 ro_config = ro_utils.readconfig(configbase) ro_file = (args[2] if len(args) >= 3 else "") ro_options = { "rofile": ro_file, "rodir": options.rodir or os.path.dirname(ro_file) } log.debug("ro_options: "+repr(ro_options)) if options.verbose: print "ro annotations -d \"%(rodir)s\" %(rofile)s "%ro_options ro_dir= ro_root_directory(progname+" annotations", ro_config, ro_options['rodir']) if not ro_dir: return 1 ro_graph = ro_manifest.readManifestGraph(ro_dir) if ro_options['rofile']: ro_file = ro_manifest.getComponentUri(ro_dir, os.path.abspath(ro_options['rofile'])) annotations = ro_graph.predicate_objects(subject=ro_file) print str(ro_file) # @@TODO figure relativization log.debug("annotations for %s"%str(ro_file)) for (atyp,aval) in annotations: aname = getAnnotationNameByUri(ro_config, atyp) log.debug("Annotations atyp %s, aname %s, aval %s"%(repr(atyp), aname, repr(aval))) print " %s: %s"%(aname,str(aval)) else: # list all annotations assert False, "@@TODO - show annotations for all RO components" return 0
def testAnnotateMultiple(self): rodir = self.createTestRo("data/ro-test-1", "RO test annotation", "ro-testRoAnnotate") rofile = rodir+"/"+"subdir1/subdir1-file.txt" annotations = ( [ {"atypename": "type", "avalue":"atype", "atypeuri":DCTERMS.type, "aexpect":"atype" } , {"atypename": "keywords", "avalue":"asubj", "atypeuri":DCTERMS.subject, "aexpect":"asubj" } , {"atypename": "description", "avalue":"adesc", "atypeuri":DCTERMS.description, "aexpect":"adesc" } , {"atypename": "format", "avalue":"aformat", "atypeuri":DCTERMS.format, "aexpect":"aformat" } , {"atypename": "title", "avalue":"atitle", "atypeuri":DCTERMS.title, "aexpect":"atitle" } , {"atypename": "created", "avalue":"acreated", "atypeuri":DCTERMS.created, "aexpect":"acreated" } #, {"atypename": ..., "avalue":..., "atypeuri":..., "aexpect":... } #, {"atypename": ..., "avalue":..., "atypeuri":..., "aexpect":... } ]) self.annotateMultiple(rodir, rofile, annotations) # Read manifest and check for annotation manifestgraph = ro_manifest.readManifestGraph(rodir) filesubj = ro_manifest.getComponentUri(rodir, "subdir1/subdir1-file.txt") for a in annotations: fileann = manifestgraph.value(filesubj, a["atypeuri"], None), self.assertEqual(len(fileann), 1, "Singleton result expected") self.assertEqual(fileann[0], a["aexpect"]) self.deleteTestRo(rodir) return
def annotate(progname, configbase, options, args): """ Annotate a specified research object component ro annotate file attribute-name [ attribute-value ] """ # Check command arguments if len(args) not in [4,5]: print ("%s annotate: wrong number of arguments provided"% (progname)) print ("Usage: %s annotate file attribute-name [ attribute-value ]"% (progname)) return 1 ro_config = ro_utils.readconfig(configbase) ro_options = { "rofile": args[2], "rodir": os.path.dirname(args[2]), "roattribute": args[3], "rovalue": args[4] or None } log.debug("ro_options: "+repr(ro_options)) # Find RO root directory ro_dir = ro_root_directory(progname+" attribute", ro_config, ro_options['rodir']) if not ro_dir: return 1 # Read and update manifest if options.verbose: print "ro annotate %(rofile)s %(roattribute)s \"%(rovalue)s\""%ro_options ro_graph = ro_manifest.readManifestGraph(ro_dir) (predicate,valtype) = getAnnotationByName(ro_config, ro_options['roattribute']) log.debug("Adding annotation predicate: %s, value %s"%(repr(predicate),repr(ro_options['rovalue']))) ro_graph.add( ( ro_manifest.getComponentUri(ro_dir, os.path.abspath(ro_options['rofile'])), predicate, rdflib.Literal(ro_options['rovalue']) ) ) ro_manifest.writeManifestGraph(ro_dir, ro_graph) return 0