view src/may/vamp/vamprdf.yeti @ 581:a9c5a29bb248

Add some library and maker properties to the plugin data; make some properties default to library-level properties if they don't exist at the plugin level
author Chris Cannam
date Tue, 10 Jun 2014 14:43:52 +0100
parents 4859ab86ec1b
children deeaef1c3cd2
line wrap: on
line source

module may.vamp.vamprdf;

//!!! todo: Test. None of this has tests yet

read = load yertle.read;
{ newRdfStore } = load yertle.store;
{ textProperty, iriProperty, nodeProperty, 
  textsProperty, irisProperty, nodesProperty } = load yertle.property;

import java.io: File;

import org.vamp_plugins: PluginLoader;

import java.lang: UnsatisfiedLinkError;

getPluginPath () =
   (try map string PluginLoader#getInstance()#getPluginPath();
    catch UnsatisfiedLinkError e: [];
    yrt);

systemVampRdfFiles () =
    concat
       (map do p:
            map ((p ^ File#separator ^) . (.name))
               (filter do entry:
                    entry.file? and
                       (lc = strLower entry.name;
                        (strEnds? lc ".ttl") or
                        (strEnds? lc ".n3") or
                        (strEnds? lc ".nt"))
                    done (listDirectory false p))
            done (getPluginPath ()));

addVampPrefixes store =
   (store.addPrefix "vamp" "http://purl.org/ontology/vamp/";
    store.addPrefix "dc" "http://purl.org/dc/elements/1.1/";
    store.addPrefix "foaf" "http://xmlns.com/foaf/0.1/";
    store.addPrefix "owl" "http://www.w3.org/2002/07/owl#";
    store.addPrefix "af" "http://purl.org/ontology/af/");

loadSystemVampRdf store =
   (addVampPrefixes store;
    for (systemVampRdfFiles ()) do file:
        case read.loadTurtleFile store ("file://" ^ file) file of
        OK (): ();
        Error e: eprintln
            "WARNING: Failed to load Vamp plugin RDF file \"\(file)\": \(e)";
        esac
    done);

getGlobalPluginIndex () =
    list (strSplit "\n" (fetchURL [ Timeout 10 ] (Handle getContents)
                         "http://www.vamp-plugins.org/rdf/plugins/index.txt"));

//!!! need to cache these retrievals
parseGlobalVampRdf () =
   (parse urls =
        case urls of
        url::rest:
           (doc = fetchURL [ Timeout 10 ] (Handle getContents) url;
            parsed = read.parseTurtleString url doc;
            { url, parsed } :. \(parse rest));
         _: [];
        esac;
    parse (getGlobalPluginIndex ()));

loadGlobalVampRdf store =
    for (parseGlobalVampRdf ()) do { url, parsed }:
        case read.loadParsedTriples store parsed of
        OK (): ();
        Error e: eprintln "WARNING: Failed to load Vamp RDF from URL \(url): \(e)";
        esac;
    done;

subjects = map (.s);

iriTypes =
    map do t:
        case t of
        IRI iri: IRI iri;
        Blank n: Blank n;
        Literal lit: failWith "Unexpected literal \"\(lit)\" in subject!";
        esac done;

iriSubjects = iriTypes . subjects;

allLibraryNodes store =
    iriSubjects
       (store.match {
            s = Wildcard (),
            p = Known (store.expand "a"),
            o = Known (store.expand "vamp:PluginLibrary")
            });

allPluginNodes store =
    iriSubjects
       (store.match {
            s = Wildcard (),
            p = Known (store.expand "a"),
            o = Known (store.expand "vamp:Plugin")
            });

pluginsWithId store id = 
    iriTypes
       (filter do pnode:
        store.contains {
            s = pnode,
            p = store.expand "vamp:identifier",
            o = Literal { value = id, type = "", language = "" }
            }
        done (allPluginNodes store));

librariesWithId store id =
    iriTypes
       (filter do lnode:
        store.contains {
            s = lnode,
            p = store.expand "vamp:identifier",
            o = Literal { value = id, type = "", language = "" }
            }
        done (allLibraryNodes store));

splitPluginKey key =
   (bits = strSplit ":" key;
    reversed = reverse bits;
    soname = strJoin ":" (reverse (tail reversed));
    identifier = head reversed;
    { soname, identifier });

pluginNodesByKey store key =
   (case splitPluginKey key of { soname, identifier }:
        candidatePlugins = pluginsWithId store identifier;
        candidateLibraries = librariesWithId store soname;
        filter do pnode:
            any do lnode:
                store.contains {
                    s = lnode,
                    p = store.expand "vamp:available_plugin",
                    o = pnode
                    }
                done candidateLibraries
            done candidatePlugins
    esac);

libraryNodesFor store pluginNode =
    map (.s) 
       (store.match {
            s = Wildcard (), 
            p = Known (store.expand "vamp:available_plugin"), 
            o = Known pluginNode
        });

libraryTextProperty store pluginNode abbr =
    case concatMap do n:
        textsProperty store n abbr
        done (libraryNodesFor store pluginNode) of
    t::_: t;
    _: "";
    esac;

libraryNodeProperty store pluginNode abbr =
    case concatMap do n:
        nodesProperty store n abbr
        done (libraryNodesFor store pluginNode) of
    (Some n)::_: Some n;
    _: None ();
    esac;

makerNodesFor store pluginNode =
    concatMap do n:
        nodesProperty store n "foaf:maker"
        done (pluginNode::(libraryNodesFor store pluginNode));

inputDomainOf store pluginNode =
   case store.match {
        s = Known pluginNode, p = Known (store.expand "vamp:input_domain"), o = Wildcard ()
        } of
    { o = IRI iri }::others:
        if IRI iri == store.expand "vamp:FrequencyDomain"
        then FrequencyDomain ()
        else TimeDomain ()
        fi;
     _: TimeDomain ();
    esac;

outputDescriptor store outputNode =
   (tprop abbr = textProperty store outputNode abbr;
    iprop abbr = iriProperty store outputNode abbr;
    bprop abbr deflt =
       (b = strLower (textProperty store outputNode abbr);
        if b == "true" then true elif b == "false" then false else deflt fi);
    nprop abbr =
        try number (textProperty store outputNode abbr); catch Exception _: 0 yrt;
    {
        identifier = tprop "vamp:identifier",
        name = tprop "dc:title",
        description = tprop "dc:description",
        rdfType = case iprop "a" of IRI iri: iri; _: "" esac,
        valueUnit = tprop "vamp:unit",
        binCount = 
            if bprop "vamp:fixed_bin_count" false
            then Known (nprop "vamp:bin_count")
            else Unknown ()
            fi,
        computes =
            case iprop "vamp:computes_event_type" of
            IRI iri: Event iri;
             _: case iprop "vamp:computes_signal_type" of
                IRI iri: Signal iri;
                 _: case iprop "vamp:computes_feature_type" of
                    IRI iri: Feature iri;
                     _: Unknown ();
                    esac
                esac
            esac,
        //!!! and some other properties
    });

pluginDataByNode store pluginNode =
   (makerNodes = makerNodesFor store pluginNode;
    libtextprop abbr = libraryTextProperty store pluginNode abbr;
    libnodeprop abbr = libraryNodeProperty store pluginNode abbr;
    textprop abbr = 
        case textProperty store pluginNode abbr of
        "": libtextprop abbr;
        text: text;
        esac;
    nodeprop abbr = 
        case nodeProperty store pluginNode abbr of
        Some s: s;
        _: libnodeprop abbr;
        esac;
    numprop abbr = try
        number (textProperty store pluginNode abbr);
        catch Exception _: 0 
        yrt;
    soname = libtextprop "vamp:identifier";
    {
        pluginNode,
        pluginKey = soname ^ ":" ^ 
           (textProperty store pluginNode "vamp:identifier"),
        library = { 
            soname, 
            name = libtextprop "dc:title",
            description = libtextprop "dc:description",
            platforms = concatMap do n:
                textsProperty store n "vamp:has_binary"
                done (libraryNodesFor store pluginNode),
            source = strLower (libtextprop "vamp:has_source") == "true",
        },
        apiVersion = numprop "vamp:vamp_API_version",
        identifier = textprop "vamp:identifier",
        name = textprop "dc:title",
        description = textprop "dc:description",
        maker =
            case textprop "foaf:maker" of
            "": case concatMap do n:
                    textsProperty store n "foaf:name"
                    done makerNodes of
                name::_: name;
                _: "";
                esac;
            name: name;
            esac,
        makerLogoURL =
            case concatMap do n:
                irisProperty store n "foaf:logo"
                done makerNodes of
            IRI iri::_: iri;
            _: "";
            esac,
        makerInfoURL =
            case concatMap do n:
                irisProperty store n "foaf:page"
                done makerNodes of
            IRI iri::_: iri;
            _: "";
            esac,
        downloadURL =
            case nodeprop "doap:download-page" of
            Some (IRI iri): iri;
            Some _: "";
            _: "";
            esac,
        copyright = textprop "dc:rights",
        version = textprop "owl:versionInfo",
        category = 
           (cat = textprop "vamp:category";
            if cat == "" then []
            else list (strSplit " > " cat)
            fi),
        inputDomain = inputDomainOf store pluginNode,
        infoURL =
            case nodeprop "foaf:page" of
            Some (IRI iri): iri;
            Some _: "";
            _: ""
            esac,
        outputs = 
           (matches = store.match { s = Known pluginNode,
                                    p = Known (store.expand "vamp:output"), 
                                    o = Wildcard () };
            array (map do t:
                       outputDescriptor store t.o;
                       done matches)),
    });

pluginKeyByNode store node =
    case libraryNodesFor store node of
    libnode::_:
        Some
           (textProperty store libnode "vamp:identifier" ^
            ":" ^
            textProperty store node "vamp:identifier");
    _: None ();
    esac;

pluginDataByKey store key =
    case pluginNodesByKey store key of
    node::_: Some (pluginDataByNode store node);
    _: None ()
    esac;

{
loadSystemVampRdf,
loadGlobalVampRdf,
allPluginNodes,
allLibraryNodes,
pluginNodesByKey,
pluginKeyByNode,
pluginDataByNode,
pluginDataByKey,
}