S-Flux SourceForge.net Logo

How does it work?

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

External applications

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>

Operations equality

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>