radiant-fabulator_exhibit-extension 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/History.txt CHANGED
@@ -1,3 +1,12 @@
1
+ === 0.0.2 2010-10-26
2
+ * 1 major enhancement:
3
+ * Provides javascript/css for implementing Exhibit views in HTML
4
+
5
+ * 3 minor enhancement:
6
+ * Explicit dependance on UUID gem
7
+ * Requires fabulator-exhibit 0.0.4
8
+ * Requires Radiant fabulator extension 0.0.6
9
+
1
10
  === 0.0.1 2010-08-10
2
11
 
3
12
  * 1 major enhancement:
data/README.markdown CHANGED
@@ -16,6 +16,9 @@ libraries:
16
16
 
17
17
  == LICENSE:
18
18
 
19
+ N.B.: The JavaScript libraries in this distribution are under a separate
20
+ license. See the JavaScript files for more information.
21
+
19
22
  Copyright (c) 2009-2010 Texas A&M University
20
23
 
21
24
  Permission is hereby granted, free of charge, to any person obtaining
data/Rakefile CHANGED
@@ -7,9 +7,10 @@ begin
7
7
  gem.email = "jgsmith@tamu.edu"
8
8
  gem.homepage = "http://github.com/jgsmith/radiant-fabulator-exhibit"
9
9
  gem.authors = ["James Smith"]
10
- gem.add_dependency('radiant-fabulator-extension', '>= 0.0.3')
11
- gem.add_dependency('fabulator-exhibit', '>= 0.0.1')
10
+ gem.add_dependency('radiant-fabulator-extension', '>= 0.0.6')
11
+ gem.add_dependency('fabulator-exhibit', '>= 0.0.4')
12
12
  gem.add_dependency('json', '>= 1.4.3')
13
+ gem.add_dependency('uuid', '>= 2.3.1')
13
14
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
14
15
  end
15
16
  rescue LoadError
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -2,6 +2,10 @@ class FabulatorExhibit < ActiveRecord::Base
2
2
  validates_presence_of :name
3
3
  validates_uniqueness_of :name
4
4
 
5
+ has_many :fabulator_exhibit_types
6
+ has_many :fabulator_exhibit_items
7
+ has_many :fabulator_exhibit_properties
8
+
5
9
  belongs_to :updated_by, :class_name => 'User'
6
10
  belongs_to :created_by, :class_name => 'User'
7
11
  end
@@ -2,7 +2,7 @@ require 'fabulator/exhibit'
2
2
  require 'json'
3
3
 
4
4
  class FabulatorExhibitExtension < Radiant::Extension
5
- version "1.0"
5
+ version "0.0.2"
6
6
  description "Exhibit extension to the Fabulator extension"
7
7
  url "http://github.com/jgsmith/radiant-fabulator-exhibit"
8
8
 
@@ -16,6 +16,13 @@ class FabulatorExhibitExtension < Radiant::Extension
16
16
  def activate
17
17
  #raise FabulatorExhibitExtension::MissingRequirement.new('FabulatorExtension must be installed and loaded first.') unless defined?(FabulatorExtension)
18
18
 
19
+ %w{exhibit.js data.js expressions.js views.js facets.js}.each do |s|
20
+ FabulatorExtension.scripts << "fabulator/exhibit/#{s}"
21
+ end
22
+ #FabulatorExtension.scripts << 'fabulator/exhibit/exhibit.js'
23
+ #FabulatorExtension.scripts << 'fabulator/exhibit/exhibit-expressions.js'
24
+ FabulatorExtension.css << 'fabulator/exhibit/exhibit.css'
25
+
19
26
  tab 'Fabulator' do
20
27
  add_item("Exhibit Databases", "/admin/fabulator/exhibits")
21
28
  end
@@ -26,7 +33,9 @@ class FabulatorExhibitExtension < Radiant::Extension
26
33
  end
27
34
  admin.exhibits = load_default_fabulator_exhibit_regions
28
35
 
29
- Fabulator::Exhibit::Actions::Lib.class_eval do
36
+ ## TODO: better database so we can have multiple applications accessing
37
+ ## the same database at the same time
38
+ Fabulator::Exhibit::Lib.class_eval do
30
39
  def self.fetch_database(nom)
31
40
  db = FabulatorExhibit.find(:first, :conditions => [ 'name = ?', nom ])
32
41
  if db.nil?
@@ -0,0 +1,30 @@
1
+ namespace :radiant do
2
+ namespace :extensions do
3
+ namespace :fabulator_exhibit do
4
+
5
+ desc "Runs the migration for the Fabulator Exhibit extension"
6
+ task :migrate => :environment do
7
+ require 'radiant/extension_migrator'
8
+ if ENV["VERSION"]
9
+ FabulatorExhibitExtension.migrator.migrate(ENV["VERSION"].to_i)
10
+ Rake::Task['db:schema:dump'].invoke
11
+ else
12
+ FabulatorExhibitExtension.migrator.migrate
13
+ Rake::Task['db:schema:dump'].invoke
14
+ end
15
+ end
16
+
17
+ desc "Copies public assets of the Fabulator Exhibit extenion to the instance public/ directory."
18
+ task :update => :environment do
19
+ is_svn_or_dir = proc { |path| path =~ /\.svn/ || File.directory?(path) }
20
+ Dir[FabulatorExhibitExtension.root + "/public/**/*"].reject(&is_svn_or_dir).each do |file|
21
+ path = file.sub(FabulatorExhibitExtension.root, '')
22
+ directory = File.dirname(path)
23
+ puts "Copying #{path}..."
24
+ mkdir_p RAILS_ROOT + directory, :verbose => false
25
+ cp file, RAILS_ROOT + path, :verbose => false
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,745 @@
1
+ /*
2
+ * (c) Copyright Texas A&M University 2010. All rights reserved.
3
+ *
4
+ * Portions of this code are copied from The SIMILE Project:
5
+ * (c) Copyright The SIMILE Project 2006. All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions
9
+ * are met:
10
+ *
11
+ * 1. Redistributions of source code must retain the above copyright
12
+ * notice, this list of conditions and the following disclaimer.
13
+ *
14
+ * 2. Redistributions in binary form must reproduce the above copyright
15
+ * notice, this list of conditions and the following disclaimer in the
16
+ * documentation and/or other materials provided with the distribution.
17
+ *
18
+ * 3. The name of the author may not be used to endorse or promote products
19
+ * derived from this software without specific prior written permission.
20
+ *
21
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ *
32
+ */
33
+
34
+ Fabulator.namespace('Exhibit');
35
+
36
+ (function($, Exhibit) {
37
+
38
+ var sources = { };
39
+
40
+ Exhibit.DataView = function(options) {
41
+ var that = { },
42
+ set = Exhibit.Set();
43
+ that.options = options;
44
+
45
+ that.events = { };
46
+ that.events.onModelChange = fluid.event.getEventFirer();
47
+
48
+ that.events.onFilterItem = fluid.event.getEventFirer(false, true);
49
+
50
+ that.registerFilter = function(ob) {
51
+ that.events.onFilterItem.addListener(function(s,i) { return ob.eventFilterItem(s,i); });
52
+ that.events.onModelChange.addListener(function(m) { ob.eventModelChange(m) });
53
+ ob.events.onFilterChange.addListener(that.eventFilterChange);
54
+ };
55
+
56
+ that.items = set.items;
57
+
58
+ that.size = set.size;
59
+
60
+ that.filterItems = function() {
61
+ var id, fres, ids;
62
+
63
+ set = Exhibit.Set();
64
+
65
+ that.items = set.items;
66
+
67
+ that.size = set.size;
68
+
69
+ ids = that.dataSource.items();
70
+
71
+ $(ids).each(function(idx, id) {
72
+ /* do filtering here */
73
+ // id = ids[id];
74
+ fres = that.events.onFilterItem.fire(that.dataSource, id);
75
+ if(fres !== false) {
76
+ set.add(id);
77
+ }
78
+ });
79
+ };
80
+
81
+ that.eventModelChange = function(model) {
82
+ var id;
83
+
84
+ that.filterItems();
85
+
86
+ that.events.onModelChange.fire(that);
87
+ };
88
+
89
+ that.eventFilterChange = function() {
90
+ var id;
91
+
92
+ that.filterItems();
93
+
94
+ that.events.onModelChange.fire(that);
95
+ };
96
+
97
+ that.getItem = function(id) {
98
+ return that.dataSource.getItem(id);
99
+ };
100
+
101
+ var createInputElement = function(inputType) {
102
+ var div = document.createElement("div");
103
+ div.innerHTML = "<input type='" + inputType + "' />";
104
+ return div.firstChild;
105
+ };
106
+
107
+ var createDOMFromTemplate = function(rootID, templateNode, result, parentElmt) {
108
+ var node, elmt, tag, attribute, value, v, n, i, items;
109
+
110
+ if(templateNode == null) {
111
+ return null;
112
+ }
113
+ else if( typeof templateNode != "object" ) {
114
+ node = document.createTextNode(templateNode);
115
+ if( parentElmt != null ) {
116
+ parentElmt.appendChild(node);
117
+ }
118
+ return node;
119
+ }
120
+ else {
121
+ elmt = null;
122
+ if( "tag" in templateNode ) {
123
+ tag = templateNode.tag;
124
+ if( parentElmt != null ) {
125
+ if( tag == "tr" ) {
126
+ elmt = parentElmt.insertRow(parentElmt.rows.length);
127
+ }
128
+ else if( tag == "td" ) {
129
+ elmt == parentElmt.insertCell(parentElmt.cells.length);
130
+ }
131
+ }
132
+ if( elmt == null ) {
133
+ elmt = tag == "input" ?
134
+ createInputElement(templateNode.type) :
135
+ document.createElement(tag);
136
+ if( parentElmt != null ) {
137
+ parentElmt.appendChild(elmt);
138
+ }
139
+ }
140
+ }
141
+ else {
142
+ elmt = templateNode.elmt;
143
+ if( parentElmt != null ) {
144
+ parentElmt.appendChild(elmt);
145
+ }
146
+ }
147
+
148
+ for(attribute in templateNode) {
149
+ value = templateNode[attribute];
150
+
151
+ if( attribute == "field" ) {
152
+ result[value] = elmt;
153
+ }
154
+ else if( attribute == "className" ) {
155
+ elmt.className = value;
156
+ }
157
+ else if( attribute == "id" ) {
158
+ elmt.id = id;
159
+ }
160
+ else if( attribute == "title" ) {
161
+ elmt.title = value;
162
+ }
163
+ else if( attribute == "type" && elm.tagName == "input") {
164
+ // do nothing
165
+ }
166
+ else if( attribute == "style" ) {
167
+ for( n in value ) {
168
+ v = value[n];
169
+ elmt.style[n] = v;
170
+ }
171
+ }
172
+ else if( attribute == "content" ) {
173
+ if( value != null ) {
174
+ items = value.evaluateOneItem(rootID, that.dataSource);
175
+ if( items.values.size() > 1 ) {
176
+ // we have a list of items
177
+ }
178
+ else if( items.values.size() == 1 ) {
179
+ elmt.innerText = (items.values.items())[0];
180
+ }
181
+ }
182
+ }
183
+ else if( attribute == "subcontentAttributes" ) {
184
+ if( value != null ) {
185
+ $(value).each(function(idx, info) {
186
+ var setting = "";
187
+
188
+ $(info.expression).each(function(idx, e) {
189
+ var r;
190
+ if(typeof(e) == "string") {
191
+ setting += e;
192
+ }
193
+ else {
194
+ r = e.evaluateOneItem(rootID, that.dataSource);
195
+ setting += (r.values.items()).join("");
196
+ }
197
+ });
198
+ $(elmt).attr(info.name, setting);
199
+ });
200
+ }
201
+ }
202
+ else if( attribute == "children" ) {
203
+ if( value != null ) {
204
+ for(i = 0, n = value.length; i < n; i++) {
205
+ createDOMFromTemplate(rootID, value[i], result, elmt);
206
+ }
207
+ }
208
+ }
209
+ else if( attribute != "tag" && attribute != "elmt" ) {
210
+ elmt.setAttribute(attribute, value);
211
+ }
212
+ }
213
+ return elmt;
214
+ }
215
+ };
216
+
217
+ that.renderTemplate = function(rootID, template) {
218
+ var result = {};
219
+ result.elmt = createDOMFromTemplate(rootID, template, result, null);
220
+
221
+ return result;
222
+ };
223
+
224
+ that.dataSource = Exhibit.DataSource({ source: options.source });
225
+ that.dataSource.events.onModelChange.addListener(that.eventModelChange);
226
+
227
+ return that;
228
+ };
229
+
230
+ Exhibit.Set = function(values) {
231
+ var that = { },
232
+ items = { },
233
+ count = 0,
234
+ recalc_items = true,
235
+ items_list = new Array();
236
+
237
+ that.isSet = true;
238
+
239
+ that.items = function() {
240
+ if(recalc_items) {
241
+ items_list = new Array();
242
+ for(i in items) {
243
+ if(typeof(i) == "string" && items[i] == true) {
244
+ items_list.push(i);
245
+ }
246
+ }
247
+ }
248
+ return items_list;
249
+ }
250
+
251
+ that.add = function(item) {
252
+ if( !(item in items) ) {
253
+ items[item] = true;
254
+ recalc_items = true;
255
+ count += 1;
256
+ }
257
+ };
258
+
259
+ that.remove = function(item) {
260
+ if( item in items ) {
261
+ delete items[item];
262
+ recalc_items = true;
263
+ count -= 1;
264
+ }
265
+ };
266
+
267
+ that.visit = function(fn) {
268
+ var o;
269
+ for(o in items) {
270
+ if(fn(o) === true) {
271
+ break;
272
+ }
273
+ }
274
+ };
275
+
276
+ that.contains = function(o) {
277
+ return( o in items );
278
+ };
279
+
280
+ that.size = function() {
281
+ if( recalc_items ) {
282
+ return that.items().length;
283
+ }
284
+ else {
285
+ return items_list.length;
286
+ }
287
+ };
288
+
289
+ if(values instanceof Array) {
290
+ $(values).each(function(idx, i) {
291
+ that.add(i);
292
+ });
293
+ }
294
+
295
+ return that;
296
+ };
297
+
298
+ Exhibit.Type = function(t) {
299
+ var that = { };
300
+
301
+ that.name = t;
302
+ that.custom = { };
303
+
304
+ return that;
305
+ };
306
+
307
+ Exhibit.Property = function(p) {
308
+ var that = { };
309
+
310
+ that.name = p;
311
+
312
+ that.getValueType = function() {
313
+ that.valueType;
314
+ };
315
+
316
+ return that;
317
+ }
318
+
319
+ Exhibit.DataSource = function(options) {
320
+ var that = { },
321
+ set = Exhibit.Set(),
322
+ labelProperty, typeProperty, uriProperty;
323
+ that.options = options;
324
+
325
+ if(typeof(sources[options.source]) != "undefined") {
326
+ return sources[options.source];
327
+ }
328
+
329
+ sources[options.source] = that;
330
+
331
+ that.source = options.source;
332
+ that.events = { };
333
+ that.events.onModelChange = fluid.event.getEventFirer();
334
+ that.events.onBeforeLoadingTypes = fluid.event.getEventFirer();
335
+ that.events.onBeforeLoadingProperties = fluid.event.getEventFirer();
336
+ that.events.onBeforeLoadingItems = fluid.event.getEventFirer();
337
+ that.events.onAfterLoadingTypes = fluid.event.getEventFirer();
338
+ that.events.onAfterLoadingProperties = fluid.event.getEventFirer();
339
+ that.events.onAfterLoadingItems = fluid.event.getEventFirer();
340
+
341
+ that.types = { };
342
+ that.properties = { };
343
+
344
+ that.spo = { };
345
+ that.ops = { };
346
+ that.items = set.items;
347
+
348
+ that.types["Item"] = Exhibit.Type("Item");
349
+
350
+ labelProperty = Exhibit.Property("label");
351
+ labelProperty.uri = "http://www.w3.org/2000/01/rdf-schema#label";
352
+ labelProperty.valueType = "text";
353
+ labelProperty.label = "Label";
354
+ labelProperty.pluralLabel = "Labels";
355
+ labelProperty.reverseLabel = "";
356
+ labelProperty.reversePluralLabel = "";
357
+ labelProperty.groupingLabel = "";
358
+ labelProperty.reverseGroupingLabel = "";
359
+ that.properties["label"] = labelProperty;
360
+
361
+ typeProperty = Exhibit.Property("type");
362
+ typeProperty.uri = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";
363
+ typeProperty.valueType = "text";
364
+ typeProperty.label = "type";
365
+ typeProperty.pluralLabel = "types";
366
+ typeProperty.reverseLabel = "";
367
+ typeProperty.reversePluralLabel = "";
368
+ typeProperty.groupingLabel = "";
369
+ typeProperty.reverseGroupingLabel = "";
370
+ that.properties["type"] = typeProperty;
371
+
372
+ uriProperty = Exhibit.Property("uri");
373
+ uriProperty.uri = "http://dh.tamu.edu/ns/fabulator/exhibit/1.0#uri";
374
+ uriProperty.valueType = "uri";
375
+ uriProperty.label = "URI";
376
+ uriProperty.pluralLabel = "URIs";
377
+ uriProperty.reverseLabel = "URI of";
378
+ uriProperty.reversePluralLabel = "URIs of";
379
+ uriProperty.groupingLabel = "URIs";
380
+ uriProperty.reverseGroupingLabel = "things named by these URIs";
381
+ that.properties["uri"] = uriProperty;
382
+
383
+ that.getItem = function(id) {
384
+ if(id in that.spo) {
385
+ return that.spo[id];
386
+ }
387
+ return { };
388
+ };
389
+
390
+ that.fetchData = function() {
391
+ /* TODO: make the URI building configurable */
392
+ $.ajax({
393
+ url: "/api/exhibits/" + options.source + ".json",
394
+ dataType: 'json',
395
+ success: function(data, textStatus) {
396
+ that.loadData(data);
397
+ }
398
+ });
399
+ };
400
+
401
+ that.loadData = function(data, baseURI) {
402
+ if(typeof baseURI == "undefined") {
403
+ baseURI = location.href;
404
+ }
405
+
406
+ if("types" in data) {
407
+ that.loadTypes(data.types, baseURI);
408
+ }
409
+
410
+ if("properties" in data) {
411
+ that.loadProperties(data.properties, baseURI);
412
+ }
413
+
414
+ if("items" in data) {
415
+ that.loadItems(data.items, baseURI);
416
+ }
417
+
418
+ that.events.onModelChange.fire(that);
419
+ };
420
+
421
+ var canonicalBaseURI = function(baseURI) {
422
+ var lastChar = baseURI.substr(baseURI.length - 1);
423
+ if( lastChar == "#" ) {
424
+ baseURI = baseURI.substr(0, baseURI.length-1) + "/";
425
+ }
426
+ else if( lastChar != "/" && lastChar != ":" ) {
427
+ baseURI += "/";
428
+ }
429
+ return baseURI;
430
+ };
431
+
432
+ that.loadTypes = function(types, baseURI) {
433
+ var typeID, typeEntry, type, p;
434
+
435
+ that.events.onBeforeLoadingTypes.fire(that);
436
+ try {
437
+ baseURI = canonicalBaseURI(baseURI);
438
+ for(typeID in types) {
439
+ if( typeof(typeID) != "string") { continue; }
440
+ typeEntry = types[typeID];
441
+ if( typeof(typeEntry) != "object") { continue; }
442
+
443
+ if( typeID in that.types ) {
444
+ type = that.types[typeID];
445
+ }
446
+ else {
447
+ type = Exhibit.Type(typeID);
448
+ that.types[typeID] = type;
449
+ }
450
+
451
+ for(p in typeEntry) {
452
+ type.custom[p] = typeEntry[p];
453
+ }
454
+
455
+ if(!("uri" in type.custom)) {
456
+ type.custom.uri = baseURI + "type#" + encodeURIComponent(typeID);
457
+ }
458
+ if(!("label" in type.custom)) {
459
+ type.custom.label = typeID;
460
+ }
461
+ }
462
+ that.events.onAfterLoadingTypes.fire(that);
463
+ }
464
+ catch(e) {
465
+ console.log("loadTypes failed:", e);
466
+ }
467
+ };
468
+
469
+ that.loadProperties = function(properties, baseURI) {
470
+ var propertyID, propertyEntry, property;
471
+
472
+ that.events.onBeforeLoadingProperties.fire(that);
473
+ try {
474
+ baseURI = canonicalBaseURI(baseURI);
475
+
476
+ for(propertyID in properties) {
477
+ if( typeof(propertyID) != "string") { continue; }
478
+ propertyEntry = properties[propertyID];
479
+ if( typeof(propertyEntry) != "object" ) { continue; }
480
+
481
+ if(propertyID in that.properties) {
482
+ property = that.properties[propertyID];
483
+ }
484
+ else {
485
+ property = Exhibit.Property(propertyID, that);
486
+ that.properties[propertyID] = property;
487
+ }
488
+
489
+ property.uri = ("uri" in propertyEntry) ? propertyEntry.uri : (baseURI + "property#" + encodeURIComponent(propertyID));
490
+ property.valueType = ("valueType" in propertyEntry) ? propertyEntry.valueType : "text";
491
+
492
+ property.label = ("label" in propertyEntry) ? propertyEntry.label : propertyID;
493
+ property.pluralLabel = ("pluralLabel" in propertyEntry) ? propertyEntry.pluralLabel : property.label;
494
+ property.reverseLabel = ("reverseLabel" in propertyEntry) ? propertyEntry.reverseLabel : "!" + property.label;
495
+ property.reversePluralLabel = ("reversePluralLabel" in propertyEntry) ? propertyEntry.reversePluralLabel : "!" + property.pluralLabel;
496
+ property.groupingLabel = ("groupingLabel" in propertyEntry) ? propertyEntry.groupingLabel : property.label;
497
+ property.reverseGroupingLabel = ("reverseGroupingLabel" in propertyEntry) ? propertyEntry.reverseGroupingLabel : "!" + property.reverseLabel;
498
+
499
+ if( "origin" in propertyEntry) {
500
+ property.origin = propertyEntry.origin;
501
+ }
502
+ }
503
+
504
+ that.events.onAfterLoadingProperties.fire(that);
505
+ }
506
+ catch(e) {
507
+ console.log("loadProperties failed: ", e);
508
+ }
509
+ };
510
+
511
+ that.loadItems = function(items, baseURI) {
512
+ var spo, ops, indexTriple, i, entry, n;
513
+
514
+ var indexPut = function(index, x, y, z) {
515
+ var hash = index[x],
516
+ array, i, n;
517
+
518
+ if(!hash) {
519
+ hash = { };
520
+ index[x] = hash;
521
+ }
522
+
523
+ array = hash[y];
524
+
525
+ if(!array) {
526
+ array = new Array();
527
+ hash[y] = array;
528
+ }
529
+ else {
530
+ for(i = 0, n = array.length; i < n; i++) {
531
+ if(z == array[i]) { return ; }
532
+ }
533
+ }
534
+ array.push(z);
535
+ };
536
+
537
+
538
+ that.events.onBeforeLoadingItems.fire(that);
539
+ try {
540
+ baseURI = canonicalBaseURI(baseURI);
541
+
542
+ indexTriple = function(s,p,o) {
543
+ indexPut(that.spo, s, p, o);
544
+ indexPut(that.ops, o, p, s);
545
+ };
546
+
547
+ for(i = 0, n = items.length; i < n; i++) {
548
+ entry = items[i];
549
+ if( typeof(entry) == "object" ) {
550
+ that.loadItem(entry, indexTriple, baseURI);
551
+ }
552
+ }
553
+ that.events.onAfterLoadingItems.fire(that);
554
+ }
555
+ catch(e) {
556
+ console.log("loadItems failed: ", e);
557
+ }
558
+ };
559
+
560
+ that.loadItem = function(item, indexFn, baseURI) {
561
+ var id, label, uri, type, isArray, p, i, n;
562
+
563
+ if(!("label" in item) && !("id" in item)) {
564
+ console.log("Item entry has no label and no id: ", item);
565
+ return;
566
+ }
567
+
568
+ if(!("label" in item)) {
569
+ id = item.id;
570
+ if( !that.items.contains(id) ) {
571
+ console.log("Cannot add new item containing no label: ", item);
572
+ }
573
+ }
574
+ else {
575
+ label = item.label;
576
+ id = ("id" in item) ? item.id : label;
577
+ uri = ("uri" in item) ? item.uri : (baseURI + "item#" + encodeURIComponent(id));
578
+ type = ("type" in item) ? item.type : "Item";
579
+
580
+ isArray = function(obj) {
581
+ if(obj.constructor.toString().indexOf("Array") == -1)
582
+ return false;
583
+ else
584
+ return true;
585
+ };
586
+
587
+ if(isArray(label)) label = label[0];
588
+ if(isArray(id)) id = id[0];
589
+ if(isArray(uri)) uri = uri[0];
590
+ if(isArray(type)) type = type[0];
591
+
592
+ set.add(id);
593
+
594
+ indexFn(id, "uri", uri);
595
+ indexFn(id, "label", label);
596
+ indexFn(id, "type", type);
597
+ indexFn(id, "id", id);
598
+
599
+ that.ensureTypeExists(type, baseURI);
600
+ }
601
+
602
+ for(p in item) {
603
+ if( typeof(p) != "string" ) { continue; }
604
+
605
+ if(p != "uri" && p != "label" && p != "id" && p != "type") {
606
+ that.ensurePropertyExists(p, baseURI);
607
+
608
+ v = item[p];
609
+ if(v instanceof Array) {
610
+ for(i = 0, n = v.length; i < n; i++) {
611
+ indexFn(id, p, v[i]);
612
+ }
613
+ }
614
+ else if( v != undefined && v != null ) {
615
+ indexFn(id, p, v);
616
+ }
617
+ }
618
+ }
619
+ };
620
+
621
+ that.ensureTypeExists = function(typeID, baseURI) {
622
+ var type;
623
+
624
+ if(!(typeID in that.types)) {
625
+ type = Exhibit.Type(typeID);
626
+ type.custom.uri = baseURI + "type#" + encodeURIComponent(typeID);
627
+ type.custom.label = typeID;
628
+ that.types[typeID] = type;
629
+ }
630
+ };
631
+
632
+ that.ensurePropertyExists = function(propertyID, baseURI) {
633
+ var property;
634
+
635
+ if(!(propertyID in that.properties)) {
636
+ property = Exhibit.Property(propertyID);
637
+ property.uri = baseURI + "property#" + encodeURIComponent(propertyID);
638
+ property.valueType = "text";
639
+
640
+ property.label = propertyID;
641
+ property.pluralLabel = property.label;
642
+
643
+ property.reverseLabel = "reverse of " + property.label;
644
+ property.reversePluralLabel = "reverse of " + property.pluralLabel;
645
+
646
+ property.groupingLabel = property.label;
647
+ property.reverseGroupingLabel = property.reverseLabel;
648
+
649
+ that.properties[propertyID] = property;
650
+ }
651
+ };
652
+
653
+ that.getProperty = function(property) {
654
+ return property in that.properties ? that.properties[property] : null;
655
+ };
656
+
657
+ var indexFillSet = function(index, x, y, set, filter) {
658
+ var hash = index[x],
659
+ array, i, n, z;
660
+
661
+ if(hash) {
662
+ array = hash[y];
663
+ if(array) {
664
+ if(filter) {
665
+ for(i = 0, n = array.length; i < n; i += 1) {
666
+ z = array[i];
667
+ if( filter.contains(z) ) {
668
+ set.add(z);
669
+ }
670
+ }
671
+ }
672
+ else {
673
+ for(i = 0, n = array.length; i < n; i += 1) {
674
+ set.add(array[i]);
675
+ }
676
+ }
677
+ }
678
+ }
679
+ };
680
+
681
+ var getUnion = function(index, xSet, y, set, filter) {
682
+ if(!set) {
683
+ set = Exhibit.Set();
684
+ }
685
+
686
+ xSet.visit(function(x) {
687
+ indexFillSet(index, x, y, set, filter);
688
+ });
689
+ return set;
690
+ };
691
+
692
+ that.getObjectsUnion = function(subjects, p, set, filter) {
693
+ return getUnion(that.spo, subjects, p, set, filter);
694
+ };
695
+
696
+ that.getSubjectsUnion = function(objects, p, set, filter) {
697
+ return getUnion(that.ops, objects, p, set, filter);
698
+ };
699
+
700
+ /*
701
+ var indexCount = function(index, x, y, filter) {
702
+ var hash = index[x],
703
+ count = 0, i, n, z;
704
+
705
+ if(hash) {
706
+ array = hash[y];
707
+ if(array) {
708
+ if(filter) {
709
+ for(i = 0, n = array.length; i < n; i += 1) {
710
+ z = array[i];
711
+ if( filter.contains(z) ) {
712
+ count += 1;
713
+ }
714
+ }
715
+ }
716
+ else {
717
+ count += array.length;
718
+ }
719
+ }
720
+ }
721
+
722
+ return count;
723
+ };
724
+
725
+ var getCount = function(index, xSet, y, filter) {
726
+ var count = 0;
727
+
728
+ xSet.visit(function(x) {
729
+ count += indexCount(index, x, y, filter);
730
+ });
731
+ return count;
732
+ };
733
+
734
+ that.countSubjects = function(objects, p, filter) {
735
+ return getCount(that.ops, objects, p, filter);
736
+ };
737
+
738
+ that.countObjects = function(objects, p, filter) {
739
+ return getCount(that.spo, objects, p, filter);
740
+ };
741
+ */
742
+
743
+ return that;
744
+ };
745
+ })(jQuery, Fabulator.Exhibit);