The main problem to solve was to find a way to let S-Flux know what an application can do on a particular kind of document (i.e. to its mymetype). The idea behind it is to let applications explain what they can do using a particular kind of language that is RDF. Using RDF documents S-Flux can understand what an application can do and present to the user only the useful informations depending on the context.
S-Flux use command line syntax to launch external applications so an
application willing to take advantage of S-Flux have to implement a
command line access to its operations. As an example consider an hypothetic
image manipulation program named imp and suppose it can process jpeg
images with a black/white filter, than it has to provide a command line sintax
similar to the following:
imp OriginalImage.jpg --blackwhite -o BlackwhiteImage.jpg
S-Flux implement a simple way to show and access functionalities of other applications. External applications expose their functionalities using RDF documents written following rules and properties defined in a set of particular OWL/RDF vocabularies (you can find them with a complete description in the schema section). Functionalities of external applications have to be accessible through a command line interface. In particular the sintax has to be as follow:
Clearly many, maybe most, applications don't conform to the syntax described
above. But, as you'll see, it's quite easy to create simple scripts that will
transform the original application command line syntax to the one used by S-Flux.
As an example consider the 'convert' application of the
ImageMagick suite.
This application let you manipulate most of the images format using the shell.
It's extremely powerful but it's sometime hard to remember its syntax and we all
know that reading man pages is sometimes boring. So why don't create an RDF document
that teach S-Flux how to use the 'convert' tool? First of all we have to create the
'wrapper' script that will translate S-Flux command line syntax to the one
understood by 'convert' (for this example I'll just consider the rotate, flip
horizontally and convert to monochrome operations):
#!/usr/bin/python import os import sys from optparse import OptionParser class convert_wrp: def __init__(self): print "Convert Wrapper" self.parser = OptionParser() self.options_list = ["--rotate","--flop", "--monochrome"] self.parser.add_option("--rotate", action="store", type="string", dest="rotate") self.parser.add_option("--flop", action="store_true", dest="flop") self.parser.add_option("--monochrome", action="store_true", dest="monochrome") self.parser.add_option("-o", "--output", action="append", type="string", dest="outputFile") (self.options, self.args) = self.parser.parse_args() def performOperation(self): command = "/usr/bin/convert" lParams = [] lParams.append(command) for inFile in self.args: lParams.append(inFile) if self.options.rotate != None: lParams.append("-rotate") lParams.append(self.options.rotate) if self.options.flop: lParams.append("-flop") if self.options.monochrome: lParams.append("-monochrome") for outFile in self.options.outputFile: lParams.append(outFile) result = os.spawnv(os.P_WAIT, command, lParams) return result convert = convert_wrp() sys.exit(convert.performOperation())
This simple Python script will convert the S-Flux syntax to the 'convert' syntax, for example the command convert_wrp.py input.jpg --rotate 90 -o output.jpg will become convert input.jpg -rotate 90 output.jpg. Of course, you can make your scripts as you like, using the language you prefer. Just make sure they are executable that means that on Windows platform you have to make a .exe file (for Pyhton scripts you can use the Py2Exe utility)
Now that we have defined the wrapper script we can write the RDF document that will be processed by S-Flux:
<?xml version="1.0"?> <!DOCTYPE rdf:RDF [<!ENTITY xsd "http://www.w3.org/2001/XMLSchema#">]> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:apps="http://sflow.org/schema/2005-06/applications#" xmlns:ops="http://sflow.org/schema/2005-06/operations#" xml:base="http://www.imagemagick.org"> <ops:Operation rdf:ID="imageRotate"> <ops:name xml:lang="en">Rotate</ops:name> <ops:name xml:lang="it">Ruota</ops:name> <ops:returnMimeType rdf:resource="http://sflow.org/data/2005-06/mimetype#sameasinput" /> <ops:shortComment xml:lang="en">Rotate the image</ops:shortComment> <ops:shortComment xml:lang="it">Ruota l'immagine</ops:shortComment> </ops:Operation> <ops:Operation rdf:ID="imageFlipH"> <ops:name xml:lang="en">Flip Horizontally</ops:name> <ops:name xml:lang="it">Ribalta orizzontalmente</ops:name> <ops:returnMimeType rdf:resource="http://sflow.org/data/2005-06/mimetype#sameasinput" /> <ops:shortComment xml:lang="en">Flip horizontally the image</ops:shortComment> <ops:shortComment xml:lang="it">Ribalta orizzontalmente l'immagine</ops:shortComment> </ops:Operation> <ops:Operation rdf:ID="imageMonochrome"> <ops:name xml:lang="en">Black and White</ops:name> <ops:name xml:lang="it">Bianco e nero</ops:name> <ops:returnMimeType rdf:resource="http://sflow.org/data/2005-06/mimetype#sameasinput" /> <ops:shortComment xml:lang="en">Make the image monochrome</ops:shortComment> <ops:shortComment xml:lang="it">Rende l'immagine monocromatica</ops:shortComment> </ops:Operation> <apps:Application rdf:ID="convert"> <apps:name>Convert</apps:name> <apps:installationPath>/home/user/wrappers</apps:installationPath> <apps:execCommand>convert_wrp.py</apps:execCommand> <apps:version>2.3</apps:version> <apps:complexity>0</apps:complexity> <apps:canWrite rdf:resource="http://sflow.org/data/2005-06/mimetype#image_jpeg" /> <apps:canWrite rdf:resource="http://sflow.org/data/2005-06/mimetype#image_gif" /> <apps:canWrite rdf:resource="http://sflow.org/data/2005-06/mimetype#image_png" /> <apps:canPerform> <rdf:Bag> <rdf:li rdf:nodeID="_convertImageRotate" /> <rdf:li rdf:nodeID="_convertImageFlipH" /> <rdf:li rdf:nodeID="_convertImageBlackWhite" /> </rdf:Bag> </apps:canPerform> </apps:Application> <rdf:Description rdf:nodeID="_convertImageRotate"> <apps:toMimeType rdf:resource="http://sflow.org/data/2005-06/mimetype#image_jpeg" /> <apps:toMimeType rdf:resource="http://sflow.org/data/2005-06/mimetype#image_gif" /> <apps:toMimeType rdf:resource="http://sflow.org/data/2005-06/mimetype#image_png" /> <apps:operation rdf:resource="#imageRotate" /> <apps:parameters> <rdf:Seq> <rdf:li rdf:nodeID="_convertImageRotate_p1" /> </rdf:Seq> </apps:parameters> </rdf:Description> <rdf:Description rdf:nodeID="_convertImageRotate_p1"> <apps:commandOption>--rotate</apps:commandOption> <apps:parameterLabel xml:lang="en">Rotation angle:</apps:parameterLabel> <apps:parameterLabel xml:lang="it">Angolo della rotazione:</apps:parameterLabel> <apps:parameterType rdf:resource="&xsd;decimal" /> <apps:parameterHelp xml:lang="en"> Clockwise rotation angle expressed in degrees number </apps:parameterHelp> <apps:parameterHelp xml:lang="it"> Angolo in gradi della rotazione in senso orario </apps:parameterHelp> </rdf:Description> <rdf:Description rdf:nodeID="_convertImageFlipH"> <apps:toMimeType rdf:resource="http://sflow.org/data/2005-06/mimetype#image_jpeg" /> <apps:toMimeType rdf:resource="http://sflow.org/data/2005-06/mimetype#image_gif" /> <apps:toMimeType rdf:resource="http://sflow.org/data/2005-06/mimetype#image_png" /> <apps:operation rdf:resource="#imageFlipH" /> <apps:parameters> <rdf:Seq> <rdf:li rdf:nodeID="_convertImageFlipH_p1" /> </rdf:Seq> </apps:parameters> </rdf:Description> <rdf:Description rdf:nodeID="_convertImageFlipH_p1"> <apps:commandOption>--flop</apps:commandOption> </rdf:Description> <rdf:Description rdf:nodeID="_convertImageBlackWhite"> <apps:toMimeType rdf:resource="http://sflow.org/data/2005-06/mimetype#image_jpeg" /> <apps:toMimeType rdf:resource="http://sflow.org/data/2005-06/mimetype#image_gif" /> <apps:toMimeType rdf:resource="http://sflow.org/data/2005-06/mimetype#image_png" /> <apps:operation rdf:resource="#imageMonochrome" /> <apps:parameters> <rdf:Seq> <rdf:li rdf:nodeID="_convertImageBlackWhite_p1" /> </rdf:Seq> </apps:parameters> </rdf:Description> <rdf:Description rdf:nodeID="_convertImageBlackWhite_p1"> <apps:commandOption>--monochrome</apps:commandOption> </rdf:Description> </rdf:RDF>
You may have noticed the definiton of the operations using the 'Operation' tag
and maybe you're asking about what happens if two different applications define
their own operations even when the operations are functionally the same.
For example consider another image processing program that is able to perform
the conversion to black and white of a jpeg image. Let say it has defined its
own 'convertToBlackAndWhite' operation. In this case S-Flux will show to the
user two different "Convert to Black and White" operations even if the concept
is just one.
It's so useful to define an application independet set of common operations and
let applications to refer to them. This is done using the owl:sameAs
attribute:
<ops:Operation rdf:ID="convertToBlackAndWhite"> <owl:sameAs rdf:resource="http://sflow.org/data/2005-06/operation#imageBlackWhite" /> <ops:name xml:lang="en">Black and White</ops:name> <ops:name xml:lang="it">Bianco e nero</ops:name> <ops:returnMimeType rdf:resource="http://sflow.org/data/2005-06/mimetype#sameasinput" /> <ops:shortComment xml:lang="en">Make the image monochrome</ops:shortComment> <ops:shortComment xml:lang="it">Rende l'immagine monocromatica</ops:shortComment> </ops:Operation>
or, more easily, you can directly refer to the independent operation definition right in your application definition with no need for you to define your operation:
<rdf:Description rdf:nodeID="_convertImageBlackWhite"> <apps:toMimeType rdf:resource="http://sflow.org/data/2005-06/mimetype#image_jpeg" /> <apps:toMimeType rdf:resource="http://sflow.org/data/2005-06/mimetype#image_gif" /> <apps:toMimeType rdf:resource="http://sflow.org/data/2005-06/mimetype#image_png" /> <apps:operation rdf:resource="http://sflow.org/data/2005-06/operation#imageBlackWhite" /> <apps:parameters> <rdf:Seq> <rdf:li rdf:nodeID="_convertImageBlackWhite_p1" /> </rdf:Seq> </apps:parameters> </rdf:Description> <rdf:Description rdf:nodeID="_convertImageBlackWhite_p1"> <apps:commandOption>--monochrome</apps:commandOption> </rdf:Description>