radiant-fabulator_exhibit-extension 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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);