API Docs for:
Show:

File: src/triplestore.js

  1. /*
  2. * $Id: src_triplestore.js.html,v 1.1 2013/06/28 16:10:02 hitoshi Exp $
  3. * This library enables web applications to easily store triples into Web Storage.
  4. * See Copyright for the status of this software.
  5. * uchida@w3.org
  6. */
  7.  
  8. /**
  9. * Triplestore wrapper for HTML5 WebStorage.
  10. * @main Triplestore
  11. * @class Triplestore
  12. * @constructor
  13. * @uses localStorage
  14. */
  15. var Triplestore = function() {
  16. this.st = localStorage;
  17. this.prefixMapping = {};
  18. this.appPrefix = "<W3C>";
  19. this.appPrefixLen = this.appPrefix.length;
  20. };
  21.  
  22. (function(){
  23. resolveQName = function(prefixMapping, qname) {
  24. if(!qname) {
  25. return null;
  26. }
  27. var resolved = null;
  28. if(isAbsoluteURI(qname)) {
  29. resolved = qname;
  30. } else {
  31. var index = qname.indexOf(":");
  32. if(index == -1) {
  33. resolved = qname;
  34. } else {
  35. var prefix = qname.substr(0, index);
  36. var iri = prefixMapping[prefix];
  37. if(iri) {
  38. resolved = iri + qname.substr(index + 1);
  39. } else {
  40. resolved = qname;
  41. }
  42. }
  43. }
  44. return resolved;
  45. };
  46. isAbsoluteURI = function(url_str) {
  47. var index = url_str.indexOf("://");
  48. return index == -1 ? false : true;
  49. };
  50. /**
  51. * Sets a mapping given a mapping and a URI to map.
  52. * @method setMapping
  53. * @param mapping {String} mapping
  54. * @param iri {String} iri
  55. * @example
  56. * st.setMapping("foaf", "http://xmlns.com/foaf/0.1/");
  57. */
  58. Triplestore.prototype.setMapping = function(mapping, iri) {
  59. this.prefixMapping[mapping] = iri;
  60. };
  61. /**
  62. * Retrieves a list of DOMStrings which are IRI identifiers for
  63. * subjects given an optional property and value to match against.
  64. * @method getSubjects
  65. * @param [property] {String} property
  66. * @param [value] {String} value
  67. * @return {Array} Sequence&lt;DOMString>
  68. * @example
  69. * st.getSubjects("foaf:name", "Bob");
  70. */
  71. Triplestore.prototype.getSubjects = function(property, value) {
  72. var hasValue = function(list, value) {
  73. for(var i = 0; list && i < list.length; i++) {
  74. if(list[i] == value) {
  75. return true;
  76. }
  77. }
  78. return false;
  79. };
  80. //init
  81. property = resolveQName(this.prefixMapping, property);
  82. value = resolveQName(this.prefixMapping, value);
  83. var res = [];
  84. for(var subject in this.st) {
  85. var props_str = this.st.getItem(subject);
  86. var props = JSON.parse(props_str);
  87. if(property) {
  88. if(value) {
  89. if(hasValue(props[property], value)) {
  90. res.push(subject.substr(this.appPrefixLen));
  91. }
  92. } else {
  93. if(props[property]) {
  94. res.push(subject.substr(this.appPrefixLen));
  95. }
  96. }
  97. } else {
  98. for(var prop in props) {
  99. if(!value || hasValue(props[prop], value)) {
  100. res.push(subject.substr(this.appPrefixLen));
  101. break;
  102. }
  103. }
  104. }
  105. }
  106. return res;
  107. };
  108. /**
  109. * Retrieves a list of DOMStrings which are IRI identifiers for
  110. * properties given an optional subject to match against.
  111. * @method getProperties
  112. * @param [subject] {String} subject
  113. * @return {Array} Sequence&lt;DOMString>
  114. * @example
  115. * st.getProperties("http://sample.org/bob");
  116. */
  117. Triplestore.prototype.getProperties = function(subject) {
  118. if(subject) {
  119. //init
  120. subject = resolveQName(this.prefixMapping, subject);
  121. subject = subject ? this.appPrefix + subject: null;
  122. var props_str = this.st.getItem(subject);
  123. var props = JSON.parse(props_str);
  124. var res = [];
  125. for(var prop in props) {
  126. res.push(prop);
  127. }
  128. return res;
  129. } else {
  130. var map = {};
  131. for(subject in this.st) {
  132. if(subject.substr(0, this.appPrefixLen) == this.appPrefix) {
  133. var props_str = this.st.getItem(subject);
  134. var props = JSON.parse(props_str);
  135. for(var prop in props) {
  136. map[prop] = null;
  137. }
  138. }
  139. }
  140. var res = [];
  141. for(var key in map) {
  142. res.push(key);
  143. }
  144. return res;
  145. }
  146. };
  147. /**
  148. * Retrieves a list of mixed types given an optional subject
  149. * and property to match against.
  150. * @method getValues
  151. * @param [subject] {String} subject
  152. * @param [property] {String} property
  153. * @return {Array} Sequence&lt;any>
  154. * @example
  155. * st.getValues("http://sample.org/bob", "foaf:name");
  156. */
  157. Triplestore.prototype.getValues = function(subject, property) {
  158. //init
  159. subject = resolveQName(this.prefixMapping, subject);
  160. property = resolveQName(this.prefixMapping, property);
  161. subject = subject ? this.appPrefix + subject: null;
  162. var subjects = [];
  163. if(subject) {
  164. subjects.push(subject);
  165. } else {
  166. for(var subject in this.st) {
  167. subjects.push(subject);
  168. }
  169. }
  170. var res = [];
  171. for(var i = 0; i < subjects.length; i++) {
  172. var subject = subjects[i];
  173. var props_str = this.st.getItem(subject);
  174. if(props_str) {
  175. var props = JSON.parse(props_str);
  176. if(property) {
  177. if(props[property]) {
  178. res = res.concat(props[property]);
  179. }
  180. } else {
  181. for(var prop in props) {
  182. res = res.concat(props[prop]);
  183. }
  184. }
  185. }
  186. }
  187. return res;
  188. };
  189. /**
  190. * Set a triple to localStorage. The old value of the property is overwritten.
  191. * @method set
  192. * @param subject {String} subject
  193. * @param property {String} property
  194. * @param value {String} value
  195. * @example
  196. * st.set("http://sample.org/bob", "foaf:name", "Bob");
  197. */
  198. Triplestore.prototype.set = function(subject, property, value) {
  199. //init
  200. subject = resolveQName(this.prefixMapping, subject);
  201. property = resolveQName(this.prefixMapping, property);
  202. value = resolveQName(this.prefixMapping, value);
  203. subject = subject ? this.appPrefix + subject: null;
  204. var props_str = this.st[subject];
  205. if(props_str) {
  206. var props = JSON.parse(props_str);
  207. props[property] = new Array(value);
  208. this.st.setItem(subject, JSON.stringify(props));
  209. } else {
  210. var props = {};
  211. props[property] = new Array(value);
  212. this.st.setItem(subject, JSON.stringify(props));
  213. }
  214. };
  215. /**
  216. * Add a triple to localStorage. If the property has already values,
  217. * the new value is concatenated to them.
  218. * @method add
  219. * @param subject {String} subject
  220. * @param property {String} property
  221. * @param value {String} value
  222. * @example
  223. * st.add("http://sample.org/bob", "foaf:name", "Bob");
  224. */
  225. Triplestore.prototype.add = function(subject, property, value) {
  226. //init
  227. subject = resolveQName(this.prefixMapping, subject);
  228. property = resolveQName(this.prefixMapping, property);
  229. value = resolveQName(this.prefixMapping, value);
  230. subject = subject ? this.appPrefix + subject: null;
  231. var props_str = this.st[subject];
  232. if(props_str) {//exist
  233. var props = JSON.parse(props_str);
  234. if(props[property]) {
  235. props[property].push(value);
  236. } else {
  237. props[property] = new Array(value);
  238. }
  239. this.st.setItem(subject, JSON.stringify(props));
  240. } else {//not exist
  241. var props = {};
  242. props[property] = new Array(value);
  243. this.st.setItem(subject, JSON.stringify(props));
  244. }
  245. };
  246. /**
  247. * Remove an subject or a property from internal storage to match against.
  248. * @method remove
  249. * @param [subject] {String} subject
  250. * @param [property] {String} property
  251. * @example
  252. * st.remove("http://sample.org/bob", "foaf:name");
  253. */
  254. Triplestore.prototype.remove = function(subject, property) {
  255. //init
  256. subject = resolveQName(this.prefixMapping, subject);
  257. property = resolveQName(this.prefixMapping, property);
  258. subject = subject ? this.appPrefix + subject: null;
  259. if(subject) {
  260. if(property) {/* remove the property */
  261. var props_str = this.st[subject];
  262. if(props_str) {
  263. var props = JSON.parse(props_str);
  264. delete props[property];
  265. this.st.setItem(subject, JSON.stringify(props));
  266. } else {
  267. throw Error("Not found " + subject + ":" + property);
  268. }
  269. } else {/* remove the subject */
  270. this.st.removeItem(subject);
  271. }
  272. } else {
  273. if(property) {/* remove all matched properties */
  274. for(var subject in this.st) {
  275. var props_str = this.st[subject];
  276. var props = JSON.parse(props_str);
  277. if(props[property]) {
  278. delete props[property];
  279. this.st.setItem(subject, JSON.stringify(props));
  280. }
  281. }
  282. } else {
  283. this.st.clear();
  284. }
  285. }
  286. };
  287. /**
  288. * Retrieves a Projection given a subject
  289. * @method getProjection
  290. * @param subject {String} subject
  291. * @return {Projection} projection
  292. * @example
  293. * st.getProjection("http://sample.org/bob");
  294. */
  295. Triplestore.prototype.getProjection = function(subject) {
  296. //init
  297. subject = resolveQName(this.prefixMapping, subject);
  298. subject = subject ? this.appPrefix + subject: null;
  299. var props_str = this.st[subject];
  300. var res = null;
  301. if(props_str) {
  302. var props = JSON.parse(props_str);
  303. res = new Projection(this, subject, props);
  304. }
  305. return res;
  306. };
  307. /**
  308. * Print the content of the storage.
  309. * @method show
  310. */
  311. Triplestore.prototype.show = function() {
  312. for(var i = 0; i < this.st.length; i++) {
  313. var subject = this.st.key(i);
  314. console.log(subject + ":" + this.st.getItem(subject));
  315. }
  316. };
  317. /**
  318. * <a href="http://www.w3.org/TR/rdfa-api/#projections">
  319. * Projection</a> class.
  320. * @class Projection
  321. * @private
  322. * @constructor
  323. */
  324. var Projection = function(store, subject, props) {
  325. this.store = store;
  326. this.st = store.st;
  327. this.prefixMapping = store.prefixMapping;
  328. this.subject = subject;
  329. this.props = props;
  330. };
  331.  
  332. /**
  333. * Retrieves the list of properties that are available on
  334. * the Projection. Each property must be an absolute URI.
  335. * @method getProperties
  336. * @return {Array} sequence&lt;String>
  337. */
  338. Projection.prototype.getProperties = function(value) {
  339. //init
  340. value = resolveQName(this.prefixMapping, value);
  341. var res = [];
  342. for(var prop in this.props) {
  343. if(value) {
  344. if(this.props[prop] == value) {
  345. res.push(prop);
  346. }
  347. } else {
  348. res.push(prop);
  349. }
  350. }
  351. return res;
  352. };
  353. /**
  354. * Retrieves the subject URI of this Projection as a string,
  355. * the value must be an absolute URI.
  356. * @method getSubject
  357. * @return {String}
  358. */
  359. Projection.prototype.getSubject = function() {
  360. return this.subject.substr(this.store.appPrefixLen);
  361. };
  362. /**
  363. * Retrieves the first property with the given name as a
  364. * language-native datatype.
  365. * @method get
  366. * @param property {String} property
  367. * @return {String}
  368. * @example
  369. * projection.get("foaf:name");
  370. */
  371. Projection.prototype.get = function(property) {
  372. var values = this.getAll(property);
  373. return values ? values[0] : null;
  374. };
  375. /**
  376. * Retrieves the list of values for a property as an array
  377. * of language-native datatypes.
  378. * @method getAll
  379. * @param property {String} The name of the property to retrieve
  380. * @return {Array} sequence&lt;String>
  381. * @example
  382. * st.getAll("foaf:name");
  383. */
  384. Projection.prototype.getAll = function(property) {
  385. //init
  386. property = resolveQName(this.prefixMapping, property);
  387. if(property) {
  388. return this.props[property] ? this.props[property] : [];
  389. } else {
  390. var res = [];
  391. for(var prop in this.props) {
  392. res = res.concat(this.props[prop]);
  393. }
  394. return res;
  395. }
  396. };
  397. Projection.prototype.remove = function() {
  398. this.st.removeItem(this.subject);
  399. };
  400. })();
  401.