active-fedora 1.1.13 → 1.2.0

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.
@@ -1,5 +1,37 @@
1
1
  require File.join( File.dirname(__FILE__), "../spec_helper" )
2
2
 
3
+ class MockAFBaseRelationship < ActiveFedora::Base
4
+ has_relationship "testing", :has_part, :type=>MockAFBaseRelationship
5
+ has_relationship "testing2", :has_member, :type=>MockAFBaseRelationship
6
+ has_relationship "testing_inbound", :has_part, :type=>MockAFBaseRelationship, :inbound=>true
7
+ has_relationship "testing_inbound2", :has_member, :type=>MockAFBaseRelationship, :inbound=>true
8
+ end
9
+
10
+ class MockAFBaseDatastream < ActiveFedora::Base
11
+ has_datastream :name=>"thumbnail",:prefix => "THUMB", :type=>ActiveFedora::Datastream, :mimeType=>"image/jpeg", :controlGroup=>'M'
12
+ has_datastream :name=>"high", :type=>ActiveFedora::Datastream, :mimeType=>"image/jpeg", :controlGroup=>'M'
13
+ end
14
+
15
+ class MockAFBaseFromSolr < ActiveFedora::Base
16
+ has_relationship "testing", :has_part, :type=>MockAFBaseFromSolr
17
+ has_relationship "testing2", :has_member, :type=>MockAFBaseFromSolr
18
+ has_relationship "testing_inbound", :has_part, :type=>MockAFBaseFromSolr, :inbound=>true
19
+ has_relationship "testing_inbound2", :has_member, :type=>MockAFBaseFromSolr, :inbound=>true
20
+
21
+ has_metadata :name => "properties", :type => ActiveFedora::MetadataDatastream do |m|
22
+ m.field "holding_id", :string
23
+ end
24
+
25
+ has_metadata :name => "descMetadata", :type => ActiveFedora::QualifiedDublinCoreDatastream do |m|
26
+ m.field "created", :date, :xml_node => "created"
27
+ m.field "language", :string, :xml_node => "language"
28
+ m.field "creator", :string, :xml_node => "creator"
29
+ # Created remaining fields
30
+ m.field "geography", :string, :xml_node => "geography"
31
+ m.field "title", :string, :xml_node => "title"
32
+ end
33
+ end
34
+
3
35
  describe ActiveFedora::Base do
4
36
 
5
37
  before(:all) do
@@ -13,7 +45,23 @@ describe ActiveFedora::Base do
13
45
 
14
46
  after(:each) do
15
47
  begin
16
- @test_object.delete
48
+ @test_object.delete
49
+ rescue
50
+ end
51
+ begin
52
+ @test_object2.delete
53
+ rescue
54
+ end
55
+ begin
56
+ @test_object3.delete
57
+ rescue
58
+ end
59
+ begin
60
+ @test_object4.delete
61
+ rescue
62
+ end
63
+ begin
64
+ @test_object5.delete
17
65
  rescue
18
66
  end
19
67
  end
@@ -207,7 +255,714 @@ describe ActiveFedora::Base do
207
255
  @test_object.delete
208
256
  ActiveFedora::Base.find_by_solr(@test_object.pid).hits.should be_empty
209
257
  end
258
+
259
+ describe '#delete' do
260
+ it 'if inbound relationships exist should remove relationships from those inbound targets as well when deleting this object' do
261
+ @test_object2 = MockAFBaseRelationship.new
262
+ @test_object2.new_object = true
263
+ @test_object2.save
264
+ @test_object3 = MockAFBaseRelationship.new
265
+ @test_object3.new_object = true
266
+ @test_object3.save
267
+ @test_object4 = MockAFBaseRelationship.new
268
+ @test_object4.new_object = true
269
+ @test_object4.save
270
+ @test_object5 = MockAFBaseRelationship.new
271
+ @test_object5.new_object = true
272
+ @test_object5.save
273
+ #append to named relationship 'testing'
274
+ @test_object2.add_named_relationship("testing",@test_object3)
275
+ @test_object2.add_named_relationship("testing2",@test_object4)
276
+ @test_object5.add_named_relationship("testing",@test_object2)
277
+ @test_object5.add_named_relationship("testing2",@test_object3)
278
+ @test_object2.save
279
+ @test_object5.save
280
+ r2 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object2)
281
+ r3 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object3)
282
+ r4 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object4)
283
+ r5 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object5)
284
+ model_rel = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>ActiveFedora::ContentModel.pid_from_ruby_class(MockAFBaseRelationship))
285
+ #check inbound correct, testing goes to :has_part and testing2 goes to :has_member
286
+ @test_object2.named_relationships(false).should == {:self=>{"testing"=>[r3.object],
287
+ "testing2"=>[r4.object]},
288
+ :inbound=>{"testing_inbound"=>[r5.object],"testing_inbound2"=>[]}}
289
+ @test_object3.named_relationships(false).should == {:self=>{"testing"=>[],"testing2"=>[]},
290
+ :inbound=>{"testing_inbound"=>[r2.object],
291
+ "testing_inbound2"=>[r5.object]}}
292
+ @test_object4.named_relationships(false).should == {:self=>{"testing"=>[],"testing2"=>[]},
293
+ :inbound=>{"testing_inbound"=>[],"testing_inbound2"=>[r2.object]}}
294
+ @test_object5.named_relationships(false).should == {:self=>{"testing"=>[r2.object],
295
+ "testing2"=>[r3.object]},
296
+ :inbound=>{"testing_inbound"=>[],"testing_inbound2"=>[]}}
297
+ @test_object2.delete
298
+ #need to reload since removed from rels_ext in memory
299
+ @test_object5 = MockAFBaseRelationship.load_instance(@test_object5.pid)
300
+
301
+ #check any test_object2 inbound rels gone from source
302
+ @test_object3.named_relationships(false).should == {:self=>{"testing"=>[],"testing2"=>[]},
303
+ :inbound=>{"testing_inbound"=>[],
304
+ "testing_inbound2"=>[r5.object]}}
305
+ @test_object4.named_relationships(false).should == {:self=>{"testing"=>[],"testing2"=>[]},
306
+ :inbound=>{"testing_inbound"=>[],"testing_inbound2"=>[]}}
307
+ @test_object5.named_relationships(false).should == {:self=>{"testing"=>[],
308
+ "testing2"=>[r3.object]},
309
+ :inbound=>{"testing_inbound"=>[],"testing_inbound2"=>[]}}
310
+
311
+ end
312
+ end
210
313
 
211
314
  end
212
315
 
316
+ describe '#remove_relationship' do
317
+ it 'should remove a relationship from an object after a save' do
318
+ @test_object2 = ActiveFedora::Base.new
319
+ @test_object.add_relationship(:has_part,@test_object2)
320
+ @test_object.save
321
+ @pid = @test_object.pid
322
+ begin
323
+ @test_object = ActiveFedora::Base.load_instance(@pid)
324
+ rescue => e
325
+ puts "#{e.message}\n#{e.backtrace}"
326
+ raise e
327
+ end
328
+ #use dummy relationships just to get correct formatting for expected objects
329
+ r = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object2)
330
+ model_rel = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>ActiveFedora::ContentModel.pid_from_ruby_class(ActiveFedora::Base))
331
+ @test_object.relationships.should == {:self=>{:has_model=>[model_rel.object],
332
+ :has_part=>[r.object]}}
333
+ @test_object.remove_relationship(:has_part,@test_object2)
334
+ @test_object.save
335
+ @test_object = ActiveFedora::Base.load_instance(@pid)
336
+ @test_object.relationships.should == {:self=>{:has_model=>[model_rel.object]}}
337
+ end
338
+ end
339
+
340
+ describe '#relationships' do
341
+ it 'should return internal relationships with no parameters and include inbound if false passed in' do
342
+ @test_object2 = MockAFBaseRelationship.new
343
+ @test_object2.new_object = true
344
+ @test_object2.save
345
+ @test_object3 = MockAFBaseRelationship.new
346
+ @test_object3.new_object = true
347
+ @test_object3.save
348
+ @test_object4 = MockAFBaseRelationship.new
349
+ @test_object4.new_object = true
350
+ @test_object4.save
351
+ @test_object5 = MockAFBaseRelationship.new
352
+ @test_object5.new_object = true
353
+ @test_object5.save
354
+ #append to named relationship 'testing'
355
+ @test_object2.testing_append(@test_object3)
356
+ @test_object2.testing2_append(@test_object4)
357
+ @test_object5.testing_append(@test_object2)
358
+ @test_object5.testing2_append(@test_object3)
359
+ @test_object2.save
360
+ @test_object5.save
361
+ r2 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object2)
362
+ r3 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object3)
363
+ r4 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object4)
364
+ r5 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object5)
365
+ model_rel = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>ActiveFedora::ContentModel.pid_from_ruby_class(MockAFBaseRelationship))
366
+ #check inbound correct, testing goes to :has_part and testing2 goes to :has_member
367
+ @test_object2.relationships(false).should == {:self=>{:has_model=>[model_rel.object],
368
+ :has_part=>[r3.object],
369
+ :has_member=>[r4.object]},
370
+ :inbound=>{:has_part=>[r5.object]}}
371
+ @test_object3.relationships(false).should == {:self=>{:has_model=>[model_rel.object]},
372
+ :inbound=>{:has_part=>[r2.object],
373
+ :has_member=>[r5.object]}}
374
+ @test_object4.relationships(false).should == {:self=>{:has_model=>[model_rel.object]},
375
+ :inbound=>{:has_member=>[r2.object]}}
376
+ @test_object5.relationships(false).should == {:self=>{:has_model=>[model_rel.object],
377
+ :has_part=>[r2.object],
378
+ :has_member=>[r3.object]},
379
+ :inbound=>{}}
380
+ #all inbound should now be empty if no parameter supplied to relationships
381
+ @test_object2.relationships.should == {:self=>{:has_model=>[model_rel.object],
382
+ :has_part=>[r3.object],
383
+ :has_member=>[r4.object]}}
384
+ @test_object3.relationships.should == {:self=>{:has_model=>[model_rel.object]}}
385
+ @test_object4.relationships.should == {:self=>{:has_model=>[model_rel.object]}}
386
+ @test_object5.relationships.should == {:self=>{:has_model=>[model_rel.object],
387
+ :has_part=>[r2.object],
388
+ :has_member=>[r3.object]}}
389
+ end
390
+ end
391
+
392
+ describe '#inbound_relationships' do
393
+ it 'should return a hash of inbound relationships' do
394
+ @test_object2 = MockAFBaseRelationship.new
395
+ @test_object2.new_object = true
396
+ @test_object2.save
397
+ @test_object3 = MockAFBaseRelationship.new
398
+ @test_object3.new_object = true
399
+ @test_object3.save
400
+ @test_object4 = MockAFBaseRelationship.new
401
+ @test_object4.new_object = true
402
+ @test_object4.save
403
+ @test_object5 = MockAFBaseRelationship.new
404
+ @test_object5.new_object = true
405
+ @test_object5.save
406
+ #append to named relationship 'testing'
407
+ @test_object2.testing_append(@test_object3)
408
+ @test_object2.testing2_append(@test_object4)
409
+ @test_object5.testing_append(@test_object2)
410
+ @test_object5.testing2_append(@test_object3)
411
+ @test_object2.save
412
+ @test_object5.save
413
+ r2 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object2)
414
+ r3 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object3)
415
+ r4 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object4)
416
+ r5 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object5)
417
+ model_rel = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>ActiveFedora::ContentModel.pid_from_ruby_class(MockAFBaseRelationship))
418
+ #check inbound correct, testing goes to :has_part and testing2 goes to :has_member
419
+ @test_object2.inbound_relationships.should == {:has_part=>[r5.object]}
420
+ @test_object3.inbound_relationships.should == {:has_part=>[r2.object],:has_member=>[r5.object]}
421
+ @test_object4.inbound_relationships.should == {:has_member=>[r2.object]}
422
+ @test_object5.inbound_relationships.should == {}
423
+ end
424
+ end
425
+
426
+ describe '#named_inbound_relationships' do
427
+ it 'should return a hash of inbound relationship names to array of objects' do
428
+ @test_object2 = MockAFBaseRelationship.new
429
+ @test_object2.new_object = true
430
+ @test_object2.save
431
+ @test_object3 = MockAFBaseRelationship.new
432
+ @test_object3.new_object = true
433
+ @test_object3.save
434
+ @test_object4 = MockAFBaseRelationship.new
435
+ @test_object4.new_object = true
436
+ @test_object4.save
437
+ @test_object5 = MockAFBaseRelationship.new
438
+ @test_object5.new_object = true
439
+ @test_object5.save
440
+ #append to named relationship 'testing'
441
+ @test_object2.testing_append(@test_object3)
442
+ @test_object2.testing2_append(@test_object4)
443
+ @test_object5.testing_append(@test_object2)
444
+ @test_object5.testing2_append(@test_object3)
445
+ @test_object2.save
446
+ @test_object5.save
447
+ r2 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object2)
448
+ r3 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object3)
449
+ r4 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object4)
450
+ r5 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object5)
451
+ model_rel = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>ActiveFedora::ContentModel.pid_from_ruby_class(MockAFBaseRelationship))
452
+ #check inbound correct, testing goes to :has_part and testing2 goes to :has_member
453
+ @test_object2.named_inbound_relationships.should == {"testing_inbound"=>[r5.object],"testing_inbound2"=>[]}
454
+ @test_object3.named_inbound_relationships.should == {"testing_inbound"=>[r2.object],"testing_inbound2"=>[r5.object]}
455
+ @test_object4.named_inbound_relationships.should == {"testing_inbound"=>[],"testing_inbound2"=>[r2.object]}
456
+ @test_object5.named_inbound_relationships.should == {"testing_inbound"=>[],"testing_inbound2"=>[]}
457
+ end
458
+ end
459
+
460
+ describe '#named_relationships' do
461
+ it '' do
462
+ @test_object2 = MockAFBaseRelationship.new
463
+ @test_object2.new_object = true
464
+ @test_object2.save
465
+ @test_object3 = MockAFBaseRelationship.new
466
+ @test_object3.new_object = true
467
+ @test_object3.save
468
+ @test_object4 = MockAFBaseRelationship.new
469
+ @test_object4.new_object = true
470
+ @test_object4.save
471
+ @test_object5 = MockAFBaseRelationship.new
472
+ @test_object5.new_object = true
473
+ @test_object5.save
474
+ #append to named relationship 'testing'
475
+ @test_object2.testing_append(@test_object3)
476
+ @test_object2.testing2_append(@test_object4)
477
+ @test_object5.testing_append(@test_object2)
478
+ @test_object5.testing2_append(@test_object3)
479
+ @test_object2.save
480
+ @test_object5.save
481
+ r2 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object2)
482
+ r3 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object3)
483
+ r4 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object4)
484
+ r5 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object5)
485
+ model_rel = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>ActiveFedora::ContentModel.pid_from_ruby_class(MockAFBaseRelationship))
486
+ #check inbound correct, testing goes to :has_part and testing2 goes to :has_member
487
+ @test_object2.named_relationships(false).should == {:self=>{"testing"=>[r3.object],
488
+ "testing2"=>[r4.object]},
489
+ :inbound=>{"testing_inbound"=>[r5.object],"testing_inbound2"=>[]}}
490
+ @test_object3.named_relationships(false).should == {:self=>{"testing"=>[],"testing2"=>[]},
491
+ :inbound=>{"testing_inbound"=>[r2.object],
492
+ "testing_inbound2"=>[r5.object]}}
493
+ @test_object4.named_relationships(false).should == {:self=>{"testing"=>[],"testing2"=>[]},
494
+ :inbound=>{"testing_inbound"=>[],"testing_inbound2"=>[r2.object]}}
495
+ @test_object5.named_relationships(false).should == {:self=>{"testing"=>[r2.object],
496
+ "testing2"=>[r3.object]},
497
+ :inbound=>{"testing_inbound"=>[],"testing_inbound2"=>[]}}
498
+ #all inbound should now be empty if no parameter supplied to relationships
499
+ @test_object2.named_relationships.should == {:self=>{"testing"=>[r3.object],
500
+ "testing2"=>[r4.object]}}
501
+ @test_object3.named_relationships.should == {:self=>{"testing"=>[],"testing2"=>[]}}
502
+ @test_object4.named_relationships.should == {:self=>{"testing"=>[],"testing2"=>[]}}
503
+ @test_object5.named_relationships.should == {:self=>{"testing"=>[r2.object],
504
+ "testing2"=>[r3.object]}}
505
+ end
506
+ end
507
+
508
+ describe '#add_named_relationship' do
509
+ it 'should add a named relationship to an object' do
510
+ @test_object2 = MockAFBaseRelationship.new
511
+ @test_object2.new_object = true
512
+ @test_object2.save
513
+ @test_object3 = MockAFBaseRelationship.new
514
+ @test_object3.new_object = true
515
+ @test_object3.save
516
+ @test_object4 = MockAFBaseRelationship.new
517
+ @test_object4.new_object = true
518
+ @test_object4.save
519
+ @test_object5 = MockAFBaseRelationship.new
520
+ @test_object5.new_object = true
521
+ @test_object5.save
522
+ #append to named relationship 'testing'
523
+ @test_object2.add_named_relationship("testing",@test_object3)
524
+ @test_object2.add_named_relationship("testing2",@test_object4)
525
+ @test_object5.add_named_relationship("testing",@test_object2)
526
+ @test_object5.add_named_relationship("testing2",@test_object3)
527
+ @test_object2.save
528
+ @test_object5.save
529
+ r2 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object2)
530
+ r3 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object3)
531
+ r4 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object4)
532
+ r5 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object5)
533
+ model_rel = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>ActiveFedora::ContentModel.pid_from_ruby_class(MockAFBaseRelationship))
534
+ #check inbound correct, testing goes to :has_part and testing2 goes to :has_member
535
+ @test_object2.named_relationships(false).should == {:self=>{"testing"=>[r3.object],
536
+ "testing2"=>[r4.object]},
537
+ :inbound=>{"testing_inbound"=>[r5.object],"testing_inbound2"=>[]}}
538
+ @test_object3.named_relationships(false).should == {:self=>{"testing"=>[],"testing2"=>[]},
539
+ :inbound=>{"testing_inbound"=>[r2.object],
540
+ "testing_inbound2"=>[r5.object]}}
541
+ @test_object4.named_relationships(false).should == {:self=>{"testing"=>[],"testing2"=>[]},
542
+ :inbound=>{"testing_inbound"=>[],"testing_inbound2"=>[r2.object]}}
543
+ @test_object5.named_relationships(false).should == {:self=>{"testing"=>[r2.object],
544
+ "testing2"=>[r3.object]},
545
+ :inbound=>{"testing_inbound"=>[],"testing_inbound2"=>[]}}
546
+ end
547
+ end
548
+
549
+ describe '#remove_named_relationship' do
550
+ it 'should remove an existing relationship from an object' do
551
+ @test_object2 = MockAFBaseRelationship.new
552
+ @test_object2.new_object = true
553
+ @test_object2.save
554
+ @test_object3 = MockAFBaseRelationship.new
555
+ @test_object3.new_object = true
556
+ @test_object3.save
557
+ @test_object4 = MockAFBaseRelationship.new
558
+ @test_object4.new_object = true
559
+ @test_object4.save
560
+ @test_object5 = MockAFBaseRelationship.new
561
+ @test_object5.new_object = true
562
+ @test_object5.save
563
+ #append to named relationship 'testing'
564
+ @test_object2.add_named_relationship("testing",@test_object3)
565
+ @test_object2.add_named_relationship("testing2",@test_object4)
566
+ @test_object5.add_named_relationship("testing",@test_object2)
567
+ @test_object5.add_named_relationship("testing2",@test_object3)
568
+ @test_object2.save
569
+ @test_object5.save
570
+ r2 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object2)
571
+ r3 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object3)
572
+ r4 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object4)
573
+ r5 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object5)
574
+ model_rel = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>ActiveFedora::ContentModel.pid_from_ruby_class(MockAFBaseRelationship))
575
+ #check inbound correct, testing goes to :has_part and testing2 goes to :has_member
576
+ @test_object2.named_relationships(false).should == {:self=>{"testing"=>[r3.object],
577
+ "testing2"=>[r4.object]},
578
+ :inbound=>{"testing_inbound"=>[r5.object],"testing_inbound2"=>[]}}
579
+ @test_object3.named_relationships(false).should == {:self=>{"testing"=>[],"testing2"=>[]},
580
+ :inbound=>{"testing_inbound"=>[r2.object],
581
+ "testing_inbound2"=>[r5.object]}}
582
+ @test_object4.named_relationships(false).should == {:self=>{"testing"=>[],"testing2"=>[]},
583
+ :inbound=>{"testing_inbound"=>[],"testing_inbound2"=>[r2.object]}}
584
+ @test_object5.named_relationships(false).should == {:self=>{"testing"=>[r2.object],
585
+ "testing2"=>[r3.object]},
586
+ :inbound=>{"testing_inbound"=>[],"testing_inbound2"=>[]}}
587
+ @test_object2.remove_named_relationship("testing",@test_object3)
588
+ @test_object2.save
589
+ #check now removed for both outbound and inbound
590
+ @test_object2.named_relationships(false).should == {:self=>{"testing"=>[],
591
+ "testing2"=>[r4.object]},
592
+ :inbound=>{"testing_inbound"=>[r5.object],"testing_inbound2"=>[]}}
593
+ @test_object3.named_relationships(false).should == {:self=>{"testing"=>[],"testing2"=>[]},
594
+ :inbound=>{"testing_inbound"=>[],
595
+ "testing_inbound2"=>[r5.object]}}
596
+ @test_object4.named_relationships(false).should == {:self=>{"testing"=>[],"testing2"=>[]},
597
+ :inbound=>{"testing_inbound"=>[],"testing_inbound2"=>[r2.object]}}
598
+ @test_object5.named_relationships(false).should == {:self=>{"testing"=>[r2.object],
599
+ "testing2"=>[r3.object]},
600
+ :inbound=>{"testing_inbound"=>[],"testing_inbound2"=>[]}}
601
+
602
+ end
603
+ end
604
+
605
+ describe '#named_relationship' do
606
+ it 'should find relationships based on name passed in for inbound or outbound' do
607
+ @test_object2 = MockAFBaseRelationship.new
608
+ @test_object2.new_object = true
609
+ @test_object2.save
610
+ @test_object3 = MockAFBaseRelationship.new
611
+ @test_object3.new_object = true
612
+ @test_object3.save
613
+ @test_object4 = MockAFBaseRelationship.new
614
+ @test_object4.new_object = true
615
+ @test_object4.save
616
+ @test_object5 = MockAFBaseRelationship.new
617
+ @test_object5.new_object = true
618
+ @test_object5.save
619
+ #append to named relationship 'testing'
620
+ @test_object2.add_named_relationship("testing",@test_object3)
621
+ @test_object2.add_named_relationship("testing2",@test_object4)
622
+ @test_object5.add_named_relationship("testing",@test_object2)
623
+ @test_object5.add_named_relationship("testing2",@test_object3)
624
+ @test_object2.save
625
+ @test_object5.save
626
+ r2 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object2)
627
+ r3 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object3)
628
+ r4 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object4)
629
+ r5 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object5)
630
+ model_rel = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>ActiveFedora::ContentModel.pid_from_ruby_class(MockAFBaseRelationship))
631
+ @test_object2.named_relationship("testing").should == [r3.object]
632
+ @test_object2.named_relationship("testing2").should == [r4.object]
633
+ @test_object2.named_relationship("testing_inbound").should == [r5.object]
634
+ @test_object2.named_relationship("testing_inbound2").should == []
635
+ @test_object3.named_relationship("testing").should == []
636
+ @test_object3.named_relationship("testing2").should == []
637
+ @test_object3.named_relationship("testing_inbound").should == [r2.object]
638
+ @test_object3.named_relationship("testing_inbound2").should == [r5.object]
639
+ @test_object4.named_relationship("testing").should == []
640
+ @test_object4.named_relationship("testing2").should == []
641
+ @test_object4.named_relationship("testing_inbound").should == []
642
+ @test_object4.named_relationship("testing_inbound2").should == [r2.object]
643
+ @test_object5.named_relationship("testing").should == [r2.object]
644
+ @test_object5.named_relationship("testing2").should == [r3.object]
645
+ @test_object5.named_relationship("testing_inbound").should == []
646
+ @test_object5.named_relationship("testing_inbound2").should == []
647
+
648
+ end
649
+ end
650
+
651
+ #
652
+ # Named datastream specs
653
+ #
654
+ describe '#add_named_datastream' do
655
+ it 'should add a datastream with the given name to the object in fedora' do
656
+ @test_object2 = MockAFBaseDatastream.new
657
+ @test_object2.new_object = true
658
+ f = File.new(File.join( File.dirname(__FILE__), "../fixtures/minivan.jpg"))
659
+ f2 = File.new(File.join( File.dirname(__FILE__), "../fixtures/dino.jpg" ))
660
+ f2.stubs(:original_filename).returns("dino.jpg")
661
+ f.stubs(:content_type).returns("image/jpeg")
662
+ @test_object2.add_named_datastream("thumbnail",{:content_type=>"image/jpeg",:blob=>f, :label=>"testDS"})
663
+ @test_object2.add_named_datastream("high",{:content_type=>"image/jpeg",:blob=>f2})
664
+ ds = @test_object2.thumbnail.first
665
+ ds2 = @test_object2.high.first
666
+ @test_object2.save
667
+ @test_object2 = MockAFBaseDatastream.load_instance(@test_object2.pid)
668
+ @test_object2.named_datastreams.keys.size.should == 2
669
+ @test_object2.named_datastreams.keys.include?("thumbnail").should == true
670
+ @test_object2.named_datastreams.keys.include?("high").should == true
671
+ @test_object2.named_datastreams["thumbnail"].size.should == 1
672
+ @test_object2.named_datastreams["high"].size.should == 1
673
+ @test_object2.named_datastreams["thumbnail"].first.attributes.should == {"label"=>ds.label,"dsid"=>ds.dsid,
674
+ "mimeType"=>ds.attributes[:mimeType],
675
+ :controlGroup=>ds.attributes[:controlGroup],
676
+ :pid=>ds.pid, :dsID=>ds.dsid, :dsLabel=>ds.attributes[:dsLabel]}
677
+ @test_object2.named_datastreams["high"].first.attributes.should == {"label"=>ds2.label,"dsid"=>ds2.dsid,
678
+ "mimeType"=>ds2.attributes[:mimeType],
679
+ :controlGroup=>ds2.attributes[:controlGroup],
680
+ :pid=>ds2.pid, :dsID=>ds2.dsid, :dsLabel=>ds2.attributes[:dsLabel]}
681
+ end
682
+ end
683
+
684
+ describe '#add_named_file_datastream' do
685
+ it 'should add a file datastream with the given name to the object in fedora' do
686
+ @test_object2 = MockAFBaseDatastream.new
687
+ @test_object2.new_object = true
688
+ f = File.new(File.join( File.dirname(__FILE__), "../fixtures/minivan.jpg"))
689
+ f.stubs(:content_type).returns("image/jpeg")
690
+ @test_object2.add_named_file_datastream("thumbnail",f)
691
+ ds = @test_object2.thumbnail.first
692
+ @test_object2.save
693
+ @test_object2 = MockAFBaseDatastream.load_instance(@test_object2.pid)
694
+ @test_object2.named_datastreams["thumbnail"].size.should == 1
695
+ @test_object2.named_datastreams["thumbnail"].first.attributes.should == {"label"=>ds.label,"dsid"=>ds.dsid,
696
+ "mimeType"=>ds.attributes[:mimeType],
697
+ :controlGroup=>ds.attributes[:controlGroup],
698
+ :pid=>ds.pid, :dsID=>ds.dsid, :dsLabel=>ds.attributes[:dsLabel]}
699
+ end
700
+ end
701
+
702
+ describe '#update_named_datastream' do
703
+ it 'should update a named datastream to have a new file' do
704
+ @test_object2 = MockAFBaseDatastream.new
705
+ @test_object2.new_object = true
706
+ f = File.new(File.join( File.dirname(__FILE__), "../fixtures/minivan.jpg"))
707
+ f2 = File.new(File.join( File.dirname(__FILE__), "../fixtures/dino.jpg" ))
708
+ f.stubs(:content_type).returns("image/jpeg")
709
+ f.stubs(:original_filename).returns("minivan.jpg")
710
+ f2.stubs(:content_type).returns("image/jpeg")
711
+ f2.stubs(:original_filename).returns("dino.jpg")
712
+ #check raise exception if dsid not supplied
713
+ @test_object2.add_named_datastream("thumbnail",{:file=>f})
714
+ @test_object2.save
715
+ @test_object2 = MockAFBaseDatastream.load_instance(@test_object2.pid)
716
+
717
+ @test_object2.thumbnail.size.should == 1
718
+ @test_object2.thumbnail_ids == ["THUMB1"]
719
+ ds = @test_object2.thumbnail.first
720
+ ds.attributes.should == {"mimeType"=>"image/jpeg",
721
+ :controlGroup=>"M", "dsid"=>"THUMB1",
722
+ :pid=>@test_object2.pid, :dsID=>"THUMB1",
723
+ "label"=>"minivan.jpg",:dsLabel=>"minivan.jpg"}
724
+ expected_content = ""
725
+ f.each {|line|
726
+ expected_content << line
727
+ }
728
+ raise "Datastream content mismatch on save of datastream" unless ds.content == expected_content
729
+ @test_object2.update_named_datastream("thumbnail",{:file=>f2,:dsid=>"THUMB1"})
730
+ @test_object2.save
731
+ @test_object2 = MockAFBaseDatastream.load_instance(@test_object2.pid)
732
+ @test_object2.thumbnail.size.should == 1
733
+ @test_object2.thumbnail_ids == ["THUMB1"]
734
+ ds = @test_object2.thumbnail.first
735
+ ds.attributes.should == {"mimeType"=>"image/jpeg",
736
+ :controlGroup=>"M", "dsid"=>"THUMB1",
737
+ :pid=>@test_object2.pid, :dsID=>"THUMB1",
738
+ "label"=>"dino.jpg", :dsLabel=>"dino.jpg"}
739
+ expected_content = ""
740
+ f2.each {|line|
741
+ expected_content << line
742
+ }
743
+ raise "Datastream content mismatch after update of datastream" unless ds.content == expected_content
744
+ end
745
+ end
746
+
747
+ describe '#named_datastreams_attributes' do
748
+ it 'should return a hash of name to hash of dsid to attribute hashes for each named datastream' do
749
+ @test_object2 = MockAFBaseDatastream.new
750
+ @test_object2.new_object = true
751
+ f = File.new(File.join( File.dirname(__FILE__), "../fixtures/minivan.jpg"))
752
+ f2 = File.new(File.join( File.dirname(__FILE__), "../fixtures/dino.jpg" ))
753
+ f2.stubs(:original_filename).returns("dino.jpg")
754
+ f.stubs(:content_type).returns("image/jpeg")
755
+ @test_object2.add_named_datastream("thumbnail",{:content_type=>"image/jpeg",:blob=>f, :label=>"testDS"})
756
+ @test_object2.add_named_datastream("high",{:content_type=>"image/jpeg",:blob=>f2})
757
+ ds = @test_object2.thumbnail.first
758
+ ds2 = @test_object2.high.first
759
+ @test_object2.save
760
+ @test_object2 = MockAFBaseDatastream.load_instance(@test_object2.pid)
761
+ @test_object2.named_datastreams_attributes.should == {"thumbnail"=>{"THUMB1"=>{"label"=>ds.label,"dsid"=>ds.dsid,
762
+ "mimeType"=>ds.attributes[:mimeType],
763
+ :controlGroup=>ds.attributes[:controlGroup],
764
+ :pid=>ds.pid, :dsID=>ds.dsid, :dsLabel=>ds.attributes[:dsLabel]}},
765
+ "high"=>{"HIGH1"=>{"label"=>ds2.label,"dsid"=>ds2.dsid,
766
+ "mimeType"=>ds2.attributes[:mimeType],
767
+ :controlGroup=>ds2.attributes[:controlGroup],
768
+ :pid=>ds2.pid, :dsID=>ds2.dsid, :dsLabel=>ds2.attributes[:dsLabel]}}}
769
+ end
770
+ end
771
+
772
+ describe '#named_datastreams_ids' do
773
+ it 'should return a hash of datastream name to an array of dsids' do
774
+ @test_object2 = MockAFBaseDatastream.new
775
+ @test_object2.new_object = true
776
+ f = File.new(File.join( File.dirname(__FILE__), "../fixtures/minivan.jpg"))
777
+ f2 = File.new(File.join( File.dirname(__FILE__), "../fixtures/dino.jpg" ))
778
+ f2.stubs(:original_filename).returns("dino.jpg")
779
+ f.stubs(:content_type).returns("image/jpeg")
780
+ @test_object2.add_named_datastream("thumbnail",{:content_type=>"image/jpeg",:blob=>f, :label=>"testDS"})
781
+ @test_object2.add_named_datastream("thumbnail",{:content_type=>"image/jpeg",:blob=>f2})
782
+ @test_object2.save
783
+ @test_object2 = MockAFBaseDatastream.load_instance(@test_object2.pid)
784
+ @test_object2.named_datastreams_ids.should == {"high"=>[], "thumbnail"=>["THUMB1", "THUMB2"]}
785
+ end
786
+ end
787
+
788
+ describe '#load_instance_from_solr' do
789
+ it 'should populate an instance of an ActiveFedora::Base object using solr instead of Fedora' do
790
+
791
+ @test_object2 = MockAFBaseFromSolr.new
792
+ @test_object2.new_object = true
793
+ attributes = {"holding_id"=>{0=>"Holding 1"},
794
+ "language"=>{0=>"Italian"},
795
+ "creator"=>{0=>"Linguist, A."},
796
+ "geography"=>{0=>"Italy"},
797
+ "title"=>{0=>"Italian and Spanish: A Comparison of Common Phrases"}}
798
+ @test_object2.update_indexed_attributes(attributes)
799
+ @test_object2.save
800
+ @test_object3 = MockAFBaseFromSolr.new
801
+ @test_object3.new_object = true
802
+ attributes = {"holding_id"=>{0=>"Holding 2"},
803
+ "language"=>{0=>"Spanish;Latin"},
804
+ "creator"=>{0=>"Linguist, A."},
805
+ "geography"=>{0=>"Spain"},
806
+ "title"=>{0=>"A study of the evolution of Spanish from Latin"}}
807
+ @test_object3.update_indexed_attributes(attributes)
808
+ @test_object3.save
809
+ @test_object4 = MockAFBaseFromSolr.new
810
+ attributes = {"holding_id"=>{0=>"Holding 3"},
811
+ "language"=>{0=>"Spanish;Latin"},
812
+ "creator"=>{0=>"Linguist, A."},
813
+ "geography"=>{0=>"Spain"},
814
+ "title"=>{0=>"An obscure look into early nomadic tribes of Spain"}}
815
+ @test_object4.update_indexed_attributes(attributes)
816
+ @test_object4.new_object = true
817
+ @test_object4.save
818
+ @test_object5 = MockAFBaseFromSolr.new
819
+ @test_object5.new_object = true
820
+ @test_object5.save
821
+
822
+ #append to named relationship 'testing'
823
+ @test_object2.testing_append(@test_object3)
824
+ @test_object2.testing2_append(@test_object4)
825
+ @test_object5.testing_append(@test_object2)
826
+ @test_object5.testing2_append(@test_object3)
827
+ @test_object2.save
828
+ @test_object5.save
829
+ r2 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object2)
830
+ r3 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object3)
831
+ r4 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object4)
832
+ r5 = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>@test_object5)
833
+ model_rel = ActiveFedora::Relationship.new(:subject=>:self, :predicate=>:dummy, :object=>ActiveFedora::ContentModel.pid_from_ruby_class(MockAFBaseFromSolr))
834
+ #check inbound correct, testing goes to :has_part and testing2 goes to :has_member
835
+ test_from_solr_object2 = MockAFBaseFromSolr.load_instance_from_solr(@test_object2.pid)
836
+ test_from_solr_object3 = MockAFBaseFromSolr.load_instance_from_solr(@test_object3.pid)
837
+ test_from_solr_object4 = MockAFBaseFromSolr.load_instance_from_solr(@test_object4.pid)
838
+ test_from_solr_object5 = MockAFBaseFromSolr.load_instance_from_solr(@test_object5.pid)
839
+
840
+ # need to check pid, system create and system modify
841
+ test_from_solr_object2.pid.should == @test_object2.pid
842
+ test_from_solr_object3.pid.should == @test_object3.pid
843
+ test_from_solr_object4.pid.should == @test_object4.pid
844
+ test_from_solr_object5.pid.should == @test_object5.pid
845
+
846
+ Time.parse(test_from_solr_object2.create_date).should == Time.parse(@test_object2.create_date)
847
+ Time.parse(test_from_solr_object3.create_date).should == Time.parse(@test_object3.create_date)
848
+ Time.parse(test_from_solr_object4.create_date).should == Time.parse(@test_object4.create_date)
849
+ Time.parse(test_from_solr_object5.create_date).should == Time.parse(@test_object5.create_date)
850
+
851
+ Time.parse(test_from_solr_object2.modified_date).should == Time.parse(@test_object2.modified_date)
852
+ Time.parse(test_from_solr_object3.modified_date).should == Time.parse(@test_object3.modified_date)
853
+ Time.parse(test_from_solr_object4.modified_date).should == Time.parse(@test_object4.modified_date)
854
+ Time.parse(test_from_solr_object5.modified_date).should == Time.parse(@test_object5.modified_date)
855
+
856
+ # need to test outbound and inbound relationships
857
+ test_from_solr_object2.relationships(false).should == {:self=>{:has_model=>[model_rel.object],
858
+ :has_part=>[r3.object],
859
+ :has_member=>[r4.object]},
860
+ :inbound=>{:has_part=>[r5.object]}}
861
+ test_from_solr_object2.named_relationships(false).should == {:self=>{"testing"=>[r3.object],"testing2"=>[r4.object]},
862
+ :inbound=>{"testing_inbound"=>[r5.object],"testing_inbound2"=>[]}}
863
+ test_from_solr_object3.relationships(false).should == {:self=>{:has_model=>[model_rel.object]},
864
+ :inbound=>{:has_part=>[r2.object],
865
+ :has_member=>[r5.object]}}
866
+ test_from_solr_object3.named_relationships(false).should == {:self=>{"testing"=>[],"testing2"=>[]},
867
+ :inbound=>{"testing_inbound"=>[r2.object],"testing_inbound2"=>[r5.object]}}
868
+ test_from_solr_object4.relationships(false).should == {:self=>{:has_model=>[model_rel.object]},
869
+ :inbound=>{:has_member=>[r2.object]}}
870
+ test_from_solr_object4.named_relationships(false).should == {:self=>{"testing"=>[],"testing2"=>[]},
871
+ :inbound=>{"testing_inbound"=>[],"testing_inbound2"=>[r2.object]}}
872
+ test_from_solr_object5.relationships(false).should == {:self=>{:has_model=>[model_rel.object],
873
+ :has_part=>[r2.object],
874
+ :has_member=>[r3.object]},
875
+ :inbound=>{}}
876
+ test_from_solr_object5.named_relationships(false).should == {:self=>{"testing"=>[r2.object],"testing2"=>[r3.object]},
877
+ :inbound=>{"testing_inbound"=>[],"testing_inbound2"=>[]}}
878
+ #all inbound should now be empty if no parameter supplied to relationships
879
+ test_from_solr_object2.relationships.should == {:self=>{:has_part=>[r3.object],:has_member=>[r4.object],:has_model=>[model_rel.object]}}
880
+ test_from_solr_object2.named_relationships.should == {:self=>{"testing"=>[r3.object],"testing2"=>[r4.object]}}
881
+ test_from_solr_object3.relationships.should == {:self=>{:has_model=>[model_rel.object]}}
882
+ test_from_solr_object3.named_relationships.should == {:self=>{"testing"=>[],"testing2"=>[]}}
883
+ test_from_solr_object4.relationships.should == {:self=>{:has_model=>[model_rel.object]}}
884
+ test_from_solr_object4.named_relationships.should == {:self=>{"testing"=>[],"testing2"=>[]}}
885
+ test_from_solr_object5.relationships.should == {:self=>{:has_model=>[model_rel.object],
886
+ :has_part=>[r2.object],
887
+ :has_member=>[r3.object]}}
888
+ test_from_solr_object5.named_relationships.should == {:self=>{"testing"=>[r2.object],"testing2"=>[r3.object]}}
889
+ # need to check metadata
890
+ test_from_solr_object2.fields[:language][:values].should == ["Italian"]
891
+ test_from_solr_object2.fields[:creator][:values].should == ["Linguist, A."]
892
+ test_from_solr_object2.fields[:geography][:values].should == ["Italy"]
893
+ test_from_solr_object2.fields[:title][:values].should == ["Italian and Spanish: A Comparison of Common Phrases"]
894
+ test_from_solr_object2.fields[:holding_id][:values].should == ["Holding 1"]
895
+
896
+ test_from_solr_object3.fields[:language][:values].should == ["Spanish;Latin"]
897
+ test_from_solr_object3.fields[:creator][:values].should == ["Linguist, A."]
898
+ test_from_solr_object3.fields[:geography][:values].should == ["Spain"]
899
+ test_from_solr_object3.fields[:title][:values].should == ["A study of the evolution of Spanish from Latin"]
900
+ test_from_solr_object3.fields[:holding_id][:values].should == ["Holding 2"]
901
+
902
+ test_from_solr_object4.fields[:language][:values].should == ["Spanish;Latin"]
903
+ test_from_solr_object4.fields[:creator][:values].should == ["Linguist, A."]
904
+ test_from_solr_object4.fields[:geography][:values].should == ["Spain"]
905
+ test_from_solr_object4.fields[:title][:values].should == ["An obscure look into early nomadic tribes of Spain"]
906
+ test_from_solr_object4.fields[:holding_id][:values].should == ["Holding 3"]
907
+
908
+ #need to check system modified and system created values correct
909
+ # need to implement for nokogiri datastream as well
910
+ #false.should == true
911
+ end
912
+ end
913
+
914
+ describe 'load_from_solr using relationship finders'
915
+ it 'resulting finder should accept :load_from_solr as :response_format and return object instantiated using load_instance_from_solr' do
916
+ # solr_result = mock("solr result")
917
+ # SpecNode.create_inbound_relationship_finders("constituents", :is_constituent_of, :inbound => true)
918
+ # local_node = SpecNode.new
919
+ # mock_repo = mock("repo")
920
+ # mock_repo.expects(:find_model).never
921
+ # SpecNode.expects(:load_instance_from_solr).times(1)
922
+ # local_node.expects(:internal_uri).returns("info:fedora/test:sample_pid")
923
+ # ActiveFedora::SolrService.instance.conn.expects(:query).with("is_constituent_of_s:info\\:fedora/test\\:sample_pid").returns(solr_result)
924
+ # local_node.constituents(:response_format => :solr).should equal(solr_result)
925
+ end
926
+
927
+ it 'when an object is loaded via solr instead of fedora it should automatically load objects from finders from solr as well' do
928
+ @test_object2 = MockAFBaseFromSolr.new
929
+ @test_object2.save
930
+ @test_object3 = MockAFBaseFromSolr.new
931
+ @test_object3.save
932
+ @test_object2.testing_append(@test_object3)
933
+ @test_object2.save
934
+
935
+ test_object2_from_solr = MockAFBaseFromSolr.load_instance_from_solr(@test_object2.pid)
936
+ test_object3_from_solr = MockAFBaseFromSolr.load_instance_from_solr(@test_object3.pid)
937
+ MockAFBaseFromSolr.expects(:load_instance_from_solr).times(4)
938
+ test_object2_from_solr.testing({:response_format=>:load_from_solr})
939
+ test_object3_from_solr.testing_inbound({:response_format=>:load_from_solr})
940
+ test_object2_from_solr.testing
941
+ test_object3_from_solr.testing_inbound
942
+ end
943
+
944
+ it 'when a load_from_solr is not set it should not call load_instance_from_solr for finders unless passing option in' do
945
+ @test_object2 = MockAFBaseFromSolr.new
946
+ @test_object2.save
947
+ @test_object3 = MockAFBaseFromSolr.new
948
+ @test_object3.save
949
+ @test_object2.testing_append(@test_object3)
950
+ @test_object2.save
951
+
952
+ MockAFBaseFromSolr.expects(:load_instance_from_solr).never()
953
+ @test_object2.testing
954
+ @test_object3.testing_inbound
955
+
956
+ #now try calling with option
957
+ MockAFBaseFromSolr.expects(:load_instance_from_solr).twice()
958
+ @test_object2.testing({:response_format=>:load_from_solr})
959
+ @test_object3.testing_inbound({:response_format=>:load_from_solr})
960
+
961
+ #now call other finder method
962
+ MockAFBaseFromSolr.expects(:load_instance_from_solr).twice()
963
+ @test_object2.testing_from_solr
964
+ @test_object3.testing_inbound_from_solr
965
+
966
+ end
967
+
213
968
  end