- /*
- * $Id: src_triplestore.js.html,v 1.1 2013/06/28 16:10:02 hitoshi Exp $
- * This library enables web applications to easily store triples into Web Storage.
- * See Copyright for the status of this software.
- * uchida@w3.org
- */
-
- /**
- * Triplestore wrapper for HTML5 WebStorage.
- * @main Triplestore
- * @class Triplestore
- * @constructor
- * @uses localStorage
- */
- var Triplestore = function() {
- this.st = localStorage;
- this.prefixMapping = {};
- this.appPrefix = "<W3C>";
- this.appPrefixLen = this.appPrefix.length;
- };
-
- (function(){
- resolveQName = function(prefixMapping, qname) {
- if(!qname) {
- return null;
- }
- var resolved = null;
- if(isAbsoluteURI(qname)) {
- resolved = qname;
- } else {
- var index = qname.indexOf(":");
- if(index == -1) {
- resolved = qname;
- } else {
- var prefix = qname.substr(0, index);
- var iri = prefixMapping[prefix];
- if(iri) {
- resolved = iri + qname.substr(index + 1);
- } else {
- resolved = qname;
- }
- }
- }
- return resolved;
- };
- isAbsoluteURI = function(url_str) {
- var index = url_str.indexOf("://");
- return index == -1 ? false : true;
- };
- /**
- * Sets a mapping given a mapping and a URI to map.
- * @method setMapping
- * @param mapping {String} mapping
- * @param iri {String} iri
- * @example
- * st.setMapping("foaf", "http://xmlns.com/foaf/0.1/");
- */
- Triplestore.prototype.setMapping = function(mapping, iri) {
- this.prefixMapping[mapping] = iri;
- };
- /**
- * Retrieves a list of DOMStrings which are IRI identifiers for
- * subjects given an optional property and value to match against.
- * @method getSubjects
- * @param [property] {String} property
- * @param [value] {String} value
- * @return {Array} Sequence<DOMString>
- * @example
- * st.getSubjects("foaf:name", "Bob");
- */
- Triplestore.prototype.getSubjects = function(property, value) {
- var hasValue = function(list, value) {
- for(var i = 0; list && i < list.length; i++) {
- if(list[i] == value) {
- return true;
- }
- }
- return false;
- };
-
- //init
- property = resolveQName(this.prefixMapping, property);
- value = resolveQName(this.prefixMapping, value);
-
- var res = [];
- for(var subject in this.st) {
- var props_str = this.st.getItem(subject);
- var props = JSON.parse(props_str);
-
- if(property) {
- if(value) {
- if(hasValue(props[property], value)) {
- res.push(subject.substr(this.appPrefixLen));
- }
- } else {
- if(props[property]) {
- res.push(subject.substr(this.appPrefixLen));
- }
- }
- } else {
- for(var prop in props) {
- if(!value || hasValue(props[prop], value)) {
- res.push(subject.substr(this.appPrefixLen));
- break;
- }
- }
- }
- }
- return res;
- };
- /**
- * Retrieves a list of DOMStrings which are IRI identifiers for
- * properties given an optional subject to match against.
- * @method getProperties
- * @param [subject] {String} subject
- * @return {Array} Sequence<DOMString>
- * @example
- * st.getProperties("http://sample.org/bob");
- */
- Triplestore.prototype.getProperties = function(subject) {
- if(subject) {
- //init
- subject = resolveQName(this.prefixMapping, subject);
- subject = subject ? this.appPrefix + subject: null;
-
- var props_str = this.st.getItem(subject);
- var props = JSON.parse(props_str);
- var res = [];
- for(var prop in props) {
- res.push(prop);
- }
- return res;
- } else {
- var map = {};
- for(subject in this.st) {
- if(subject.substr(0, this.appPrefixLen) == this.appPrefix) {
- var props_str = this.st.getItem(subject);
- var props = JSON.parse(props_str);
- for(var prop in props) {
- map[prop] = null;
- }
- }
- }
- var res = [];
- for(var key in map) {
- res.push(key);
- }
- return res;
- }
- };
- /**
- * Retrieves a list of mixed types given an optional subject
- * and property to match against.
- * @method getValues
- * @param [subject] {String} subject
- * @param [property] {String} property
- * @return {Array} Sequence<any>
- * @example
- * st.getValues("http://sample.org/bob", "foaf:name");
- */
- Triplestore.prototype.getValues = function(subject, property) {
- //init
- subject = resolveQName(this.prefixMapping, subject);
- property = resolveQName(this.prefixMapping, property);
- subject = subject ? this.appPrefix + subject: null;
-
- var subjects = [];
- if(subject) {
- subjects.push(subject);
- } else {
- for(var subject in this.st) {
- subjects.push(subject);
- }
- }
-
- var res = [];
- for(var i = 0; i < subjects.length; i++) {
- var subject = subjects[i];
- var props_str = this.st.getItem(subject);
- if(props_str) {
- var props = JSON.parse(props_str);
-
- if(property) {
- if(props[property]) {
- res = res.concat(props[property]);
- }
- } else {
- for(var prop in props) {
- res = res.concat(props[prop]);
- }
- }
- }
- }
- return res;
- };
- /**
- * Set a triple to localStorage. The old value of the property is overwritten.
- * @method set
- * @param subject {String} subject
- * @param property {String} property
- * @param value {String} value
- * @example
- * st.set("http://sample.org/bob", "foaf:name", "Bob");
- */
- Triplestore.prototype.set = function(subject, property, value) {
- //init
- subject = resolveQName(this.prefixMapping, subject);
- property = resolveQName(this.prefixMapping, property);
- value = resolveQName(this.prefixMapping, value);
- subject = subject ? this.appPrefix + subject: null;
-
- var props_str = this.st[subject];
- if(props_str) {
- var props = JSON.parse(props_str);
- props[property] = new Array(value);
- this.st.setItem(subject, JSON.stringify(props));
- } else {
- var props = {};
- props[property] = new Array(value);
- this.st.setItem(subject, JSON.stringify(props));
- }
- };
- /**
- * Add a triple to localStorage. If the property has already values,
- * the new value is concatenated to them.
- * @method add
- * @param subject {String} subject
- * @param property {String} property
- * @param value {String} value
- * @example
- * st.add("http://sample.org/bob", "foaf:name", "Bob");
- */
- Triplestore.prototype.add = function(subject, property, value) {
- //init
- subject = resolveQName(this.prefixMapping, subject);
- property = resolveQName(this.prefixMapping, property);
- value = resolveQName(this.prefixMapping, value);
- subject = subject ? this.appPrefix + subject: null;
-
- var props_str = this.st[subject];
- if(props_str) {//exist
- var props = JSON.parse(props_str);
- if(props[property]) {
- props[property].push(value);
- } else {
- props[property] = new Array(value);
- }
- this.st.setItem(subject, JSON.stringify(props));
- } else {//not exist
- var props = {};
- props[property] = new Array(value);
- this.st.setItem(subject, JSON.stringify(props));
- }
- };
- /**
- * Remove an subject or a property from internal storage to match against.
- * @method remove
- * @param [subject] {String} subject
- * @param [property] {String} property
- * @example
- * st.remove("http://sample.org/bob", "foaf:name");
- */
- Triplestore.prototype.remove = function(subject, property) {
- //init
- subject = resolveQName(this.prefixMapping, subject);
- property = resolveQName(this.prefixMapping, property);
- subject = subject ? this.appPrefix + subject: null;
-
- if(subject) {
- if(property) {/* remove the property */
- var props_str = this.st[subject];
- if(props_str) {
- var props = JSON.parse(props_str);
- delete props[property];
- this.st.setItem(subject, JSON.stringify(props));
- } else {
- throw Error("Not found " + subject + ":" + property);
- }
- } else {/* remove the subject */
- this.st.removeItem(subject);
- }
- } else {
- if(property) {/* remove all matched properties */
- for(var subject in this.st) {
- var props_str = this.st[subject];
- var props = JSON.parse(props_str);
- if(props[property]) {
- delete props[property];
- this.st.setItem(subject, JSON.stringify(props));
- }
- }
- } else {
- this.st.clear();
- }
- }
- };
- /**
- * Retrieves a Projection given a subject
- * @method getProjection
- * @param subject {String} subject
- * @return {Projection} projection
- * @example
- * st.getProjection("http://sample.org/bob");
- */
- Triplestore.prototype.getProjection = function(subject) {
- //init
- subject = resolveQName(this.prefixMapping, subject);
- subject = subject ? this.appPrefix + subject: null;
-
- var props_str = this.st[subject];
- var res = null;
- if(props_str) {
- var props = JSON.parse(props_str);
- res = new Projection(this, subject, props);
- }
- return res;
- };
- /**
- * Print the content of the storage.
- * @method show
- */
- Triplestore.prototype.show = function() {
- for(var i = 0; i < this.st.length; i++) {
- var subject = this.st.key(i);
- console.log(subject + ":" + this.st.getItem(subject));
- }
- };
-
- /**
- * <a href="http://www.w3.org/TR/rdfa-api/#projections">
- * Projection</a> class.
- * @class Projection
- * @private
- * @constructor
- */
- var Projection = function(store, subject, props) {
- this.store = store;
- this.st = store.st;
- this.prefixMapping = store.prefixMapping;
- this.subject = subject;
- this.props = props;
- };
-
- /**
- * Retrieves the list of properties that are available on
- * the Projection. Each property must be an absolute URI.
- * @method getProperties
- * @return {Array} sequence<String>
- */
- Projection.prototype.getProperties = function(value) {
- //init
- value = resolveQName(this.prefixMapping, value);
-
- var res = [];
- for(var prop in this.props) {
- if(value) {
- if(this.props[prop] == value) {
- res.push(prop);
- }
- } else {
- res.push(prop);
- }
- }
- return res;
- };
- /**
- * Retrieves the subject URI of this Projection as a string,
- * the value must be an absolute URI.
- * @method getSubject
- * @return {String}
- */
- Projection.prototype.getSubject = function() {
- return this.subject.substr(this.store.appPrefixLen);
- };
- /**
- * Retrieves the first property with the given name as a
- * language-native datatype.
- * @method get
- * @param property {String} property
- * @return {String}
- * @example
- * projection.get("foaf:name");
- */
- Projection.prototype.get = function(property) {
- var values = this.getAll(property);
- return values ? values[0] : null;
- };
- /**
- * Retrieves the list of values for a property as an array
- * of language-native datatypes.
- * @method getAll
- * @param property {String} The name of the property to retrieve
- * @return {Array} sequence<String>
- * @example
- * st.getAll("foaf:name");
- */
- Projection.prototype.getAll = function(property) {
- //init
- property = resolveQName(this.prefixMapping, property);
-
- if(property) {
- return this.props[property] ? this.props[property] : [];
- } else {
- var res = [];
- for(var prop in this.props) {
- res = res.concat(this.props[prop]);
- }
- return res;
- }
- };
- Projection.prototype.remove = function() {
- this.st.removeItem(this.subject);
- };
- })();
-
-