      1 // exports
      2 exports.Store = {};
      3
      4 /**
      5  * @namespace
      6  *
      7  * The Store module defines the public interface to the RDF store.
      8  */
      9 var Store = exports.Store;
     10
     11 // imports
     12 var QueryEngine = require("./../../js-query-engine/src/query_engine").QueryEngine;
     13 var QuadBackend = require("./../../js-rdf-persistence/src/quad_backend").QuadBackend;
     14 var Lexicon = require("./../../js-rdf-persistence/src/lexicon").Lexicon;
     15 var RDFJSInterface = require("./../../js-query-engine/src/rdf_js_interface").RDFJSInterface;
     16 var RDFStoreClient = require("./../../js-connection/src/rdfstore_client").RDFStoreClient;
     17 var Worker = require('webworker');
     18
     19 /**
     20  * Version of the store
     21  */
     22 Store.VERSION = "0.4.15";
     23
     24 /**
     25  * Create a new RDFStore instance that will be
     26  * executed in a web worker in the browser or a new process
     27  * in Node.js.
     28  * <br/>
     29  * <br/>
     30  * The first argument to this function is the URL/FS location
     31  * of the store script.
     32  * <br/>
     33  * <br/>
     34  * This parameter is mandatory in the browser. It is safe to
     35  * ignore this parameter in Node.js.
     36  * <br/>
     37  * <br/>
     38  * If support for web workers is not present, a regular
     39  * store object will be initialized and returned.
     40  * <br/>
     41  * <br/>
     42  *
     43  * @param {String} [scriptPath] URL of the RDFStore script
     44  * @param {Object[]} [args] Arguments to be passed to the store that will be created
     45  * @param {Function} callback Callback function that will be invoked with an error flag and the connection/store object.
     46  */
     47 Store.connect = function() {
     48     var path, args, callback;
     49     if(arguments.length == 1) {
     50         path = __dirname;
     51         args = {};
     52         callback = arguments[0];
     53     } if(arguments.length == 2) {
     54         if(typeof(arguments[0]) === 'string') {
     55             path = arguments[0];
     56             args = {};
     57         } else {
     58             path = __dirname+"/index.js";
     59             args = arguments[0];
     60         }
     61         callback = arguments[1];
     62     } else {
     63         path = arguments[0];
     64         args = arguments[1];
     65         callback = arguments[2];
     66     }
     67     try {
     68         if(!!Worker) {
     69             new RDFStoreClient.RDFStoreClient(path, args, function(success,connection) {
     70                 callback(success, connection);
     71             });
     72         } else {
     73             Store.create(args,function(connection){
     74                 callback(false, connection);
     75             });
     76         }
     77     } catch(e) {
     78         Store.create(args,function(connection){
     79             callback(false, connection);
     80         });
     81     }
     82 };
     83
     84 /**
     85  * Creates a new instance of the store.
     86  *
     87  * The function accepts two optional arguments.
     88  * <br/>
     89  * If only one argument is passed it must be a
     90  * callback function that will be invoked when the
     91  * store had been created.<br/>
     92  * <br/>
     93  * If two arguments are passed the first one must
     94  * be a map of configuration parameters for the
     95  * store, and the second one the callback function.<br/>
     96  * <br/>
     97  * Take a look at the Store constructor function for
     98  * a detailed list of possible configuration parameters.<br/>
     99  *
    100  * @param {Object[]} [args] Arguments to be passed to the store that will be created
    101  * @param {Function} [callback] Callback function that will be invoked with an error flag and the connection/store object.
    102  */
    103 Store.create = function(){
    104     if(arguments.length == 1) {
    105         return new Store.Store(arguments[0]);
    106     } else if(arguments.length == 2) {
    107         return new Store.Store(arguments[0], arguments[1]);
    108     } else {
    109         return new Store.Store();
    110     };
    111 };
    112
    113 /**
    114  * Creates a new store.<br/>
    115  * <br/>
    116  * It accepts two optional arguments, a map of configuration
    117  * options for the store and a callback function.<br/>
    118  *
    119  * @constructor
    120  * @param {Function} [callback] Callback that will be invoked when the store has been created
    121  * @param {Object} [params]
    122  * <ul>
    123  *  <li> persistent:  should use persistence? </li>
    124  *  <li> name: if using persistence, the name for this store </li>
    125  *  <li> maxCacheSize: if using persistence, maximum size of the index cache </li>
    126  * </ul>
    127  */
    128 Store.Store = function(arg1, arg2) {
    129     var callback = null;
    130     var params   = null;
    131
    132     if(arguments.length == 0) {
    133         params ={};
    134     } else if(arguments.length == 1) {
    135         params   = {};
    136         callback = arg1;
    137     } else if(arguments.length > 1) {
    138         params   = arg1;
    139         callback = arg2;
    140     } else {
    141         throw("An optional argument map and a callback must be provided");
    142     }
    143
    144     if(params['treeOrder'] == null) {
    145         params['treeOrder'] = 15;
    146     }
    147
    148     this.functionMap = {};
    149
    150     var that = this;
    151     new Lexicon.Lexicon(function(lexicon){
    152         if(params['overwrite'] === true) {
    153             // delete lexicon values
    154             lexicon.clear();
    155         }
    156         new QuadBackend.QuadBackend(params, function(backend){
    157             if(params['overwrite'] === true) {
    158                 // delete index values
    159                 backend.clear();
    160             }
    161             params.backend = backend;
    162             params.lexicon =lexicon;
    163             that.engine = new QueryEngine.QueryEngine(params);
    164             if(callback) {
    165                 callback(that);
    166             }
    167         });
    168     },
    169     params['name']);
    170 };
    171
    172
    173 /**
    174  * An instance of RDF JS Interface <code>RDFEnvironment</code>
    175  * associated to this graph instance.
    176  */
    177 Store.Store.prototype.rdf = RDFJSInterface.rdf;
    178
    179 /**
    180  * Executes a query in the store.<br/>
    181  * <br/>
    182  * There are two possible ways of invoking this function,
    183  * providing a pair of arrays of namespaces that will be
    184  * used to compute the union of the default and named
    185  * dataset, or without them.
    186  * <br/>
    187  * <br/>
    188  * Both invocations receive as an optional last parameter
    189  * a callback function that will receive the return status
    190  * of the query and the results.
    191  * <br/>
    192  * <br/>
    193  * Results can have different formats:
    194  * <ul>
    195  *  <li> SELECT queries: array of binding maps </li>
    196  *  <li> CONSTRUCT queries: RDF JS Interface Graph object </li>
    197  *  <li> ASK queries: JS boolean value </li>
    198  *  <li> LOAD/INSERT... queries: Number of triples modified/inserted </li>
    199  * </ul>
    200  *
    201  * @arguments:
    202  * @param {String} query
    203  * @param {String} [defaultURIs] default namespaces
    204  * @param {String} [namespacesURIs] named namespaces
    205  * @param {Function} [callback]
    206  */
    207 Store.Store.prototype.execute = function() {
    208     if(arguments.length === 3) {
    209         this.executeWithEnvironment(arguments[0],
    210                                     arguments[1],
    211                                     arguments[2]);
    212     } else if(arguments.length === 4) {
    213         this.executeWithEnvironment(arguments[0],
    214                                     arguments[1],
    215                                     arguments[2],
    216                                     arguments[3]);
    217     } else {
    218
    219         var queryString;
    220         var callback;
    221
    222         if(arguments.length === 1) {
    223             queryString = arguments[0];
    224             var callback = function(){};
    225         } else if(arguments.length === 2) {
    226             queryString = arguments[0];
    227             callback = arguments [1];
    228         }
    229         this.engine.execute(queryString, callback);
    230     }
    231 };
    232
    233 /**
    234  * A variation of the execute function that expects
    235  * arguments containing values for the default and named
    236  * graphs that will be used in the query.
    237  *
    238  *
    239  * @arguments:
    240  * @param {String} query
    241  * @param {String} URIs default namespaces
    242  * @param {String} URIs named namespaces
    243  * @param {Function} [callback]
    244  */
    245 Store.Store.prototype.executeWithEnvironment = function() {
    246     var queryString, defaultGraphs, namedGraphs;
    247
    248     if(arguments.length === 3) {
    249         queryString   = arguments[0];
    250         // JSDoc fails if this is pushed outside
    251         var callback  = function(){};
    252         defaultGraphs = arguments[1];
    253         namedGraphs   = arguments[2];
    254     } else if(arguments.length === 4) {
    255         queryString   = arguments[0];
    256         var callback      = arguments [3];
    257         defaultGraphs = arguments[1];
    258         namedGraphs   = arguments[2];
    259     }
    260     this.engine.execute(queryString, callback, defaultGraphs, namedGraphs);
    261 };
    262
    263 /**
    264  * Retrieves all the quads belonging to a certain graph
    265  * in the store as a RDF JS Interface Graph object.<br/>
    266  * <br/>
    267  * The function accepts as mandatory parameter a callback
    268  * function that will receive the returned graph.<br/>
    269  * <br/>
    270  * Optionally, the URI of the graph can also be passed as
    271  * the first argument. If no graph is specified, the
    272  * default graph will be returned.<br/>
    273  *
    274  * @arguments
    275  * @param {String} [graphURI] If this parameter is missing, the default graph will be returned
    276  * @param {Functon} callback
    277  */
    278 Store.Store.prototype.graph = function() {
    279     var graphUri = null;
    280     var callback = null;
    281     if(arguments.length === 1) {
    282         callback = arguments[0] || function(){};
    283         graphUri = this.engine.lexicon.defaultGraphUri;
    284     } else if(arguments.length === 2) {
    285         callback = arguments[1] || function(){};
    286         graphUri = arguments[0];
    287     } else {
    288         throw("An optional graph URI and a callback function must be provided");
    289     }
    290
    291     if(this.rdf.resolve(graphUri) != null) {
    292         graphUri = this.rdf.resolve(graphUri);
    293     }
    294
    295     this.engine.execute("CONSTRUCT { ?s ?p ?o } WHERE { GRAPH <" + graphUri + "> { ?s ?p ?o } }", callback);
    296 };
    297
    298 /**
    299  * Retrieves all the quads belonging to a certain node
    300  * in the store as a RDF JS Interface Graph object containing
    301  * the collection of triples whose subject is the provided
    302  * node URI.<br/>
    303  * <br/>
    304  * The function accepts as mandatory parameters the node URI and
    305  * a callback unction that will receive the returned node.<br/>
    306  * <br/>
    307  * Optionally, the URI of the graph where the node is contained
    308  * can also be passed as the first argument. <br/>
    309  * <br/>
    310  * If no graph is specified, the node will be looked into the
    311  * default graph.<br/>
    312  *
    313  * @arguments
    314  * @param {String} nodeURI URI of the node to look for
    315  * @param {String} [graphURI] If this parameter is missing, the node will be looked into the default graph
    316  * @param {Functon} callback
    317  */
    318 Store.Store.prototype.node = function() {
    319     var graphUri = null;
    320     var callback = null;
    321     var nodeUri  = null;
    322     if(arguments.length === 2) {
    323         nodeUri = arguments[0];
    324         callback = arguments[1] || function(){};
    325         graphUri = this.engine.lexicon.defaultGraphUri;
    326     } else if(arguments.length === 3) {
    327         nodeUri = arguments[0];
    328         graphUri = arguments[1];
    329         callback = arguments[2] || function(){};
    330     } else {
    331         throw("An optional graph URI, node URI and a callback function must be provided");
    332     }
    333
    334     if(this.rdf.resolve(graphUri) != null) {
    335         graphUri = this.rdf.resolve(graphUri);
    336     }
    337
    338     if(this.rdf.resolve(nodeUri) != null) {
    339         nodeUri = this.rdf.resolve(nodeUri);
    340     }
    341
    342     this.engine.execute("CONSTRUCT { <" + nodeUri + "> ?p ?o } WHERE { GRAPH <" + graphUri + "> { <" + nodeUri + "> ?p ?o } }", callback);
    343 };
    344
    345 /**
    346  * Associates an event listener function to a node URI. Every time the collection
    347  * of triples whose subject is the specified node URI changes, because an
    348  * insertion or deletion, the provided callback function will be invoked
    349  * receiving as a parameter a RDF JS Interface Graph object with the new
    350  * collection of triples.<br/>
    351  * <br/>
    352  * The function accepts two mandatory arguments, the URI of the node to observe
    353  * and the function that will receive the event notifications. An optional
    354  * third parameter, consisting of a callback function, can be passed and will be invoked
    355  * once the store had correctly configured the event listener.<br/>
    356  *<br/>
    357  * LOAD queries, batch loading data into the store, do not
    358  * trigger events by default. If you wish to be notified
    359  * by changes triggered by this kind of queries, invoke
    360  * the *setBatchLoadEvents* function with a true argument.<br/>
    361  *<br/>
    362  * The event listener function can be removed using the stopObservingNode function.
    363  *
    364  * @arguments
    365  * @param {String} nodeURI URI of the node to observe
    366  * @param {Function} eventListener Function that will be notified with the events
    367  * @param {Function} [callback] Function that will be invoked, once the event listener had been correctly set up.
    368  */
    369 Store.Store.prototype.startObservingNode = function() {
    370     var uri, graphUri, callback;
    371
    372     if(arguments.length === 2) {
    373         uri = arguments[0];
    374         callback = arguments[1];
    375         this.engine.callbacksBackend.observeNode(uri, callback, function(){});
    376     } else if(arguments.length === 3) {
    377         uri = arguments[0];
    378         graphUri = arguments[1];
    379         callback = arguments[2];
    380         this.engine.callbacksBackend.observeNode(uri, graphUri, callback, function(){});
    381     }
    382 };
    383
    384 /**
    385  * Removes a callback function associated to a node.<br/>
    386  * The event listener function object must be passed as an argument.<br/>
    387  *
    388  * @arguments
    389  * @param {Function} eventListener The event listener function to remove, the same passed as an argument to startObservingNode
    390  */
    391 Store.Store.prototype.stopObservingNode = function(callback) {
    392     this.engine.callbacksBackend.stopObservingNode(callback);
    393 };
    394
    395 /**
    396  * Associates an event listener function to a SPARQL SELECT or
    397  * CONSTRUCT query.<br/>
    398  * Every time an update (insert, delete...) query modified the
    399  * triples in the store in a way that modifies the output of the
    400  * query, the event listener will be invoked with an updated
    401  * result.<br/>
    402  *<br/>
    403  * LOAD queries, batch loading data into the store, do not
    404  * trigger events by default. If you wish to be notified
    405  * by changes triggered by this kind of queries, invoke
    406  * the <code>setBatchLoadEvents</code> function with a true argument.<br/>
    407  *<br/>
    408  * The event listener function can be removed invoking the
    409  * <code>stopObservingQuery</code> function.
    410  *
    411  * @arguments
    412  * @param {String} query SELECT or CONSTRUCT SPARQL query
    413  * @param {Function} eventListener the function that will receive the notifications
    414  * @param {Function} [callback] optional function that will be invoked when the stored had set up the event listener function.
    415  */
    416 Store.Store.prototype.startObservingQuery = function() {
    417     var query = arguments[0];
    418     var callback = arguments[1];
    419     var endCallback = arguments[2];
    420     if(endCallback!=null) {
    421         this.engine.callbacksBackend.observeQuery(query, callback, endCallback);
    422     } else {
    423         this.engine.callbacksBackend.observeQuery(query, callback, function(){});
    424     }
    425 };
    426
    427 /**
    428  * Removes a callback function associated to a SPARQL query.<br/>
    429  * The event listener function object must be passed as an argument.
    430  *
    431  * @arguments
    432  * @param {Function} eventListener The event listener function to remove, the same passed as an argument to startObservingQuery
    433  */
    434 Store.Store.prototype.stopObservingQuery = function(query) {
    435     this.engine.callbacksBackend.stopObservingQuery(query);
    436 };
    437
    438 /**
    439  * Associates an event listener to a pattern expressed as the
    440  * subject, predicate, object and graph string parameters passed
    441  * to the function. To match any value in that position, a <code>null</code>
    442  * value can be passed as an argument. e.g. <code>subscribe(null, null, null, g, cb)</code>,
    443  * will be notified with any change in the g graph.<br/>
    444  * The graph component of the pattern does not support a <code>null</code> value.<br/>
    445  *<br/>
    446  * Results will be notified as an Array of RDF JS Interface
    447  * <code>Triple</code> objects.<br/>
    448  *<br/>
    449  * LOAD queries, batch loading data into the store, do not
    450  * trigger events by default. If you wish to be notified
    451  * by changes triggered by this kind of queries, invoke
    452  * the <code>setBatchLoadEvents</code> function with a true argument.
    453  *
    454  * @arguments
    455  * @param {String} s subject or null for any subject
    456  * @param {String} p predicate or null for any predicate
    457  * @param {String} o object or null for any object
    458  * @param {String} g graph or null for any graph
    459  * @param {Function} event listener function that will be notified when a change occurs
    460  */
    461 Store.Store.prototype.subscribe = function(s, p, o, g, callback) {
    462     var adapterCb = function(event,triples){
    463         var acum = [];
    464         var queryEnv = {blanks:{}, outCache:{}};
    465         var bindings = [];
    466
    467         for(var i=0; i<triples.length; i++) {
    468             var triple = triples[i];
    469             var s = RDFJSInterface.buildRDFResource(triple.subject,bindings,this.engine,queryEnv);
    470             var p = RDFJSInterface.buildRDFResource(triple.predicate,bindings,this.engine,queryEnv);
    471             var o = RDFJSInterface.buildRDFResource(triple.object,bindings,this.engine,queryEnv);
    472             if(s!=null && p!=null && o!=null) {
    473                 triple = new RDFJSInterface.Triple(s,p,o);
    474                 acum.push(triple);
    475             }
    476         }
    477
    478         callback(event,acum);
    479     };
    480
    481     this.functionMap[callback] = adapterCb;
    482     this.engine.callbacksBackend.subscribe(s,p,o,g,adapterCb,function(){});
    483 };
    484
    485 /**
    486  * Removes an event listener associated to a certain pattern.
    487  * The function passed as an argument to <code>subscribe</code> must be
    488  * passed as an argument.
    489  *
    490  * @arguments
    491  * @param {Function} callback The event listener to be removed
    492  */
    493 Store.Store.prototype.unsubscribe = function(callback) {
    494     var adapterCb = this.functionMap[callback];
    495     this.engine.callbacksBackend.unsubscribe(adapterCb);
    496     delete this.functionMap[callback];
    497 };
    498
    499 /**
    500  * Register a combination of prefix and URI fragment in the default instance
    501  * of the RDF JS Interface API <code>RDFEnvironment</code> object associated
    502  * to the store and available through the <code>storeInstance.rdf</code> property.
    503  *
    504  * @arguments
    505  * @param {String} prefix The prefix to be associated
    506  * @param {String} URIFragment URI fragment the provided prefix will be resolved
    507  */
    508 Store.Store.prototype.setPrefix = function(prefix, uri) {
    509     this.rdf.setPrefix(prefix, uri);
    510 };
    511
    512 /**
    513  * Defines the URI that will be used by default by the RDF JS Interface
    514  * API <code>RDFEnvironment</code> object associated to the store and available
    515  * through the <code>storeInstance.rdf</code> property.
    516  *
    517  * @arguments
    518  * @param {String} URIFragment The URI fragment will be used by default
    519  */
    520 Store.Store.prototype.setDefaultPrefix = function(uri) {
    521     this.rdf.setDefaultPrefix(uri);
    522 };
    523
    524 /**
    525  * Inserts a RDF JS Interface API <code>Graph</code> object into the store.
    526  * The function receives a mandatory <code>Graph</code> object whose triples
    527  * will be inserted. Optionally, a URI string for a graph and a
    528  * callback function can be passed as arguments.<br/>
    529  * <br/>
    530  * If no graph URI is specified, triples will be inserted into the
    531  * default graph.<br/>
    532  * <br/>
    533  * If the callback function is specified, it will be invoked when all the
    534  * triples had been inserted into the store.<br/>
    535  *
    536  * @arguments
    537  * @param {RDFJSInterface.Graph} triples a RDF JS Interface <code>Graph</code> object
    538  * @param {String} [graphURI] URI of the graph where the triples will be inserted. If it is missing, triples will be inserted in the default graph
    539  * @param {String} [callback] A callback function that will be invoked with a success notification and the number of triples inserted
    540  */
    541 Store.Store.prototype.insert = function() {
    542     var graph;
    543     var triples;
    544     var callback;
    545     if(arguments.length === 1) {
    546         triples = arguments[0];
    547     } else if(arguments.length === 2) {
    548         graph = this.rdf.createNamedNode(this.engine.lexicon.defaultGraphUri);
    549         triples = arguments[0];
    550         callback= arguments[1] || function(){};
    551     } else if(arguments.length === 3) {
    552         triples = arguments[0];
    553         graph = this.rdf.createNamedNode(arguments[1]);
    554         callback= arguments[2] || function(){};
    555     } else {
    556         throw("The triples to insert, an optional graph and callback must be provided");
    557     }
    558
    559     var query = "";
    560     var that = this;
    561     triples.forEach(function(triple) {
    562         query = query + that._nodeToQuery(triple.subject) + that._nodeToQuery(triple.predicate) + that._nodeToQuery(triple.object) + ".";
    563     });
    564
    565     if(graph != null) {
    566         query = "INSERT DATA { GRAPH " + this._nodeToQuery(graph) +" { "+ query + " } }";
    567     } else {
    568         query = "INSERT DATA { " + this._nodeToQuery(graph) +" { "+ query + " }";
    569     }
    570
    571     this.engine.execute(query, callback);
    572 };
    573
    574 Store.Store.prototype._nodeToQuery = function(term) {
    575     if(term.interfaceName === 'NamedNode') {
    576         var resolvedUri = this.rdf.resolve(term.valueOf());
    577         if(resolvedUri != null) {
    578             return "<" + resolvedUri + ">";
    579         } else {
    580             return "<" + term.valueOf() + ">";
    581         }
    582     } else if(term.interfaceName === '') {
    583         return term.toString();
    584     } else {
    585         if(term.lang != null) {
    586             return "\""+term.valueOf()+"\"@"+term.lang;
    587         } else if(term.datatype != null) {
    588             return "\""+term.valueOf()+"\"^^<"+term.datatype+">";
    589         }
    590         return term.toString();
    591     }
    592 };
    593
    594 /**
    595  * Removes the triples in a RDF JS Interface API <code>Graph</code> object from the store.
    596  * The function receives a mandatory <code>Graph</code> object whose triples
    597  * will be removed. Optionally, a URI string for a graph and a
    598  * callback function can be passed as arguments.<br/>
    599  * <br/>
    600  * If no graph URI is specified, triples will be removed from the
    601  * default graph.<br/>
    602  * <br/>
    603  * If the callback function is specified, it will be invoked when all the
    604  * triples had been removed from the store.
    605  *
    606  * @arguments
    607  * @param {RDFJSInterface.Graph} triples a RDF JS Interface <code>Graph</code> object
    608  * @param {String} [graphURI] URI of the graph where the triples will be removed from. If it is missing, triples will be removed from the default graph
    609  * @param {String} [callback] A callback function that will be invoked with a success notification
    610  */
    611 Store.Store.prototype.delete = function() {
    612
    613     var graph;
    614     var triples;
    615     var callback;
    616     if(arguments.length === 1) {
    617         triples = arguments[0];
    618     } else if(arguments.length === 2) {
    619         graph = this.rdf.createNamedNode(this.engine.lexicon.defaultGraphUri);
    620         triples = arguments[0];
    621         callback= arguments[1] || function(){};
    622     } else if(arguments.length === 3) {
    623         triples = arguments[0];
    624         graph = this.rdf.createNamedNode(arguments[1]);
    625         callback= arguments[2] || function(){};
    626     } else {
    627         throw("The triples to delete, an optional graph and callback must be provided");
    628     }
    629
    630     var query = "";
    631     var that = this;
    632     triples.forEach(function(triple) {
    633         query = query + that._nodeToQuery(triple.subject) + that._nodeToQuery(triple.predicate) + that._nodeToQuery(triple.object) + ".";
    634     });
    635
    636     if(graph != null) {
    637         query = "DELETE DATA { GRAPH " + this._nodeToQuery(graph) +" { "+ query + " } }";
    638     } else {
    639         query = "DELETE DATA { " + this._nodeToQuery(graph) +" { "+ query + " }";
    640     }
    641
    642     this.engine.execute(query, callback);
    643 };
    644
    645 /**
    646  * Removes all the triples stored in a graph.
    647  *
    648  * The URI of the graph and a callback function can be
    649  * optinally passed as parameters.<br/>
    650  * <br/>
    651  * If no graph URI is specified, all triples in the
    652  * default graph will be removed.
    653  *
    654  * @arguments
    655  * @param {String} [graph] the URI of the graph the triples must be removed from
    656  * @param {Function} [callback] a function that will be invoked with a success notification
    657  */
    658 Store.Store.prototype.clear = function() {
    659     var graph;
    660     var callback;
    661
    662     if(arguments.length === 0) {
    663         graph = this.rdf.createNamedNode(this.engine.lexicon.defaultGraphUri);
    664         var callback= function(){};
    665     } else if(arguments.length === 1) {
    666         graph = this.rdf.createNamedNode(this.engine.lexicon.defaultGraphUri);
    667         callback= arguments[0] || function(){};
    668     } else if(arguments.length === 2) {
    669         graph = this.rdf.createNamedNode(arguments[0]);
    670         callback= arguments[1] || function(){};
    671     } else {
    672         throw("The optional graph and a callback must be provided");
    673     }
    674
    675     var query = "CLEAR GRAPH " + this._nodeToQuery(graph);
    676     this.engine.execute(query, callback);
    677 };
    678
    679 /**
    680  * Boolean value determining if loading RDF must produce
    681  * triple add events and fire callbacks.<br/>
    682  * Default value is false.
    683  *
    684  * @arguments
    685  * @param {boolean} mustFireEvents true/false value.
    686  */
    687 Store.Store.prototype.setBatchLoadEvents = function(mustFireEvents){
    688     this.engine.eventsOnBatchLoad = mustFireEvents;
    689 };
    690
    691 /**
    692  * Registers a namespace prefix that will be automatically declared
    693  * in all the queries.<br/>
    694  * <br/>
    695  * The prefix will also be inserte in the default <code>RDFEnvironment</code> object
    696  * associated to the <code>rdf</code> property of the store instance.
    697  *
    698  * @arguments
    699  * @param {String} ns the name space to be regsitered
    700  * @param {String} prefix the URI fragment associated to the name space
    701  */
    702 Store.Store.prototype.registerDefaultNamespace = function(ns, prefix) {
    703     this.rdf.prefixes.set(ns,prefix);
    704     this.engine.registerDefaultNamespace(ns,prefix);
    705 };
    706
    707 /**
    708  * Registers the default namespaces declared in the RDF JS Interfaces
    709  * specification in the default Profile.
    710  */
    711 Store.Store.prototype.registerDefaultProfileNamespaces = function() {
    712     var defaultNsMap = this.rdf.prefixes.values();
    713     for (var p in defaultNsMap) {
    714         this.registerDefaultNamespace(p,defaultNsMap[p]);
    715     }
    716 };
    717
    718 /**
    719  * Load triples into a graph in the store. Data can be passed directly to the method
    720  * or a remote URI speifying where the data is located can be used.<br/>
    721  *<br/>
    722  * If the data is passed directly to the load function, the media type stating the format
    723  * of the data must also be passed to the function.<br/>
    724  *<br/>
    725  * If an URI is passed as a parameter, the store will attempt to perform content negotiation
    726  * with the remote server and get a representation for the RDF data matching one of the
    727  * the RDF parsers registered in the store. In this case, the media type parameter must be
    728  * set to the <code>'remote'</code> value.<br/>
    729  *<br/>
    730  * An additional URI for the graph where the parsed data will be loaded and a callback function
    731  * can be also passed as parameters. If no graph is specified, triples will be loaded in the
    732  * default graph.<br/>
    733  *<br/>
    734  * By default loading data will not trigger notification through the events API. If events needs to
    735  * be trigger, the functio <code>setBatchLoadEvents</code> must be invoked with a true parameter.
    736  *
    737  * @arguments
    738  * @param {String} mediaType Media type (application/json, text/n3...) of the data to be parsed or the value <code>'remote'</code> if a URI for the data is passed instead
    739  * @param {String} [graph] Graph where the parsed triples will be inserted. If it is not specified, triples will be loaded in the default graph
    740  * @param {String} data RDF data to be parsed and loaded or an URI where the data will be retrieved after performing content negotiation
    741  * @param {Function} callback that will be invoked with a success notification and the number of triples loaded.
    742  */
    743 Store.Store.prototype.load = function(){
    744     var mediaType;
    745     var data;
    746     var graph;
    747     var callback;
    748
    749     if(arguments.length === 3) {
    750         graph = this.rdf.createNamedNode(this.engine.lexicon.defaultGraphUri);
    751         mediaType = arguments[0];
    752         data = arguments[1];
    753         callback= arguments[2] || function(){};
    754     } else if(arguments.length === 4) {
    755         mediaType = arguments[0];
    756         data = arguments[1];
    757         graph = this.rdf.createNamedNode(arguments[2]);
    758         callback= arguments[3] || function(){};
    759     } else if(arguments.length === 2) {
    760         throw("The mediaType of the parser, the data a callback and an optional graph must be provided");
    761     }
    762
    763     if(mediaType === 'remote') {
    764         data = this.rdf.createNamedNode(data);
    765         var query = "LOAD <"+data.valueOf()+"> INTO GRAPH <"+graph.valueOf()+">";
    766
    767         this.engine.execute(query, callback);
    768     } else if(data && typeof(data)==='string' && data.indexOf('file://')=== 0) {
    769         var parser = this.engine.rdfLoader.parsers[mediaType];
    770
    771         var that = this;
    772         this.engine.rdfLoader.loadFromFile(parser, {'token':'uri', 'value':graph.valueOf()}, data, function(success, quads) {
    773             if(success) {
    774                 that.engine.batchLoad(quads,callback);
    775             } else {
    776                 callback(success, quads);
    777             }
    778         });
    779
    780
    781     } else {
    782         var parser = this.engine.rdfLoader.parsers[mediaType];
    783
    784         var that = this;
    785
    786         this.engine.rdfLoader.tryToParse(parser, {'token':'uri', 'value':graph.valueOf()}, data, function(success, quads) {
    787             if(success) {
    788                 that.engine.batchLoad(quads,callback);
    789             } else {
    790                 callback(success, quads);
    791             }
    792         });
    793     }
    794 };
    795
    796 /**
    797  * Registers a new parser associated to the provided media type. If there is a parser already registered for
    798  * that media type, the new parser will replace the old one.<br/>
    799  *<br/>
    800  * Parsers must implement a function *parse* accepting the data to be parsed as the
    801  * first parameter and the destination graph URI as the second one.
    802  * They must return an array of objects with properties: 'subject', 'predicate', 'object'
    803  * and 'graph' containing lexical representations for these values:
    804  *<br/>
    805  *<ul>
    806  * <li><code>{literal: '"literal"'}</code></li>
    807  * <li><code>{literal: ''"literal"^^<datatype>'}</code></li>
    808  * <li><code>{literal: '"literal"@lang'}</code></li>
    809  * <li><code>{uri: 'uri'}</code></li>
    810  * <li><code>{blank: '_:label'}</code></li>
    811  *</ul>
    812  *<br/>
    813  * The provided media type will be used to perform content negotiation when dealing with remote
    814  * resources, or to select the parser in the <code>load</code> function.
    815  *
    816  * @arguments
    817  * @param {String} mediaType the media type for this parser
    818  * @param {String} parser an object containing the *parse* function with the parser logic
    819  */
    820 Store.Store.prototype.registerParser = function(mediaType, parser) {
    821     this.engine.rdfLoader.registerParser(mediaType,parser);
    822 };
    823
    824 /**
    825  * Returns the URI of all the graphs currently contained
    826  * in the store
    827  *
    828  * @arguments:
    829  * @param {Function} callback function that will receive a success notification and the array of graph URIs
    830  */
    831 Store.Store.prototype.registeredGraphs = function(callback) {
    832     var graphs = this.engine.lexicon.registeredGraphs(true);
    833     var acum = [];
    834     for(var i=0; i<graphs.length; i++) {
    835         var graph = graphs[i];
    836         var uri = new RDFJSInterface.NamedNode(graph);
    837         acum.push(uri);
    838     }
    839
    840     return callback(true, acum);
    841 };
    842
    843 /** @private */
    844 Store.Store.prototype._nodeToQuery = function(term) {
    845     if(term.interfaceName === 'NamedNode') {
    846         var resolvedUri = this.rdf.resolve(term.valueOf());
    847         if(resolvedUri != null) {
    848             return "<" + resolvedUri + ">";
    849         } else {
    850             return "<" + term.valueOf() + ">";
    851         }
    852     } else if(term.interfaceName === '') {
    853         return term.toString();
    854     } else {
    855         return term.toString();
    856     }
    857 };
    858
    859 /**
    860  * Returns the current network transport being used by the
    861  * the store.
    862  *
    863  * The default transport uses TCP sockets in the Node.js version
    864  * and relies on jQuery in the browser version. This can be overriden
    865  * using the <code>setNetworkTransport</code> function.
    866  */
    867 Store.Store.prototype.getNetworkTransport = function() {
    868     return NetworkTransport;
    869 };
    870
    871 /**
    872  * Sets the network transport used by the store.<br/>
    873  * <br/>
    874  * Network transport consist of an object implementing the <code>load</code>
    875  * function, receiving the URI to load, a string with the value
    876  * of the HTTP 'Accept' header for the store registered parsers,
    877  * a callback function where the retrieved data and the success notification
    878  * must be returned.<br/>
    879  *<br/>
    880  * Different examples with implementations of different transports can be found
    881  * in the source code of the store:
    882  *<ul>
    883  * <li>src/js-communication/src/tcp_transport.js</li>
    884  * <li>src/js-communication/src/ajax_transport.js</li>
    885  *</ul>
    886  * @arguments
    887  * @param networkTransportImpl object implementing the transport *load* function.
    888  */
    889 Store.Store.prototype.setNetworkTransport = function(networkTransportImpl) {
    890     NetworkTransport = networkTransportImpl;
    891 };
    892