active-fedora 2.3.0 → 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ class SampleAFObjRelationshipQueryParam < ActiveFedora::Base
2
+ #points to all parents linked via is_member_of
3
+ has_relationship "parents", :is_member_of
4
+ #returns only parents that have a level value set to "series"
5
+ has_relationship "series_parents", :is_member_of, :query_params=>{:q=>{"level_t"=>"series"}}
6
+ #returns all parts
7
+ has_relationship "parts", :is_part_of, :inbound=>true
8
+ #returns only parts that have level to "series"
9
+ has_relationship "series_parts", :is_part_of, :inbound=>true, :query_params=>{:q=>{"level_t"=>"series"}}
10
+ has_bidirectional_relationship "bi_series_parts", :has_part, :is_part_of, :query_params=>{:q=>{"level_t"=>"series"}}
11
+ end
@@ -5,10 +5,12 @@ require "active_fedora/samples/marpa-dc_datastream.rb"
5
5
 
6
6
  # This is an example of an ActiveFedora Model
7
7
  #
8
- # Some of the datastream ids were chosen based on the Hydra modeling conventions. You don't have to follow them in your work. ActiveFedora itself has no notion of those conventions, but we do encourage you to use them.
8
+ # Some of the datastream ids were chosen based on the Hydra modeling conventions. You don't have to follow them in your work.
9
+ # ActiveFedora itself has no notion of those conventions, but we do encourage you to use them.
9
10
  #
10
11
  # The Hydra conventions encourage you to have a datastream with this dsid whose contents are descriptive metadata like MODS or Dublin Core. They especially encourage MODS.
11
- # The rightsMetadata datastream is also a convention provided by the Hydra Common Metadata "content model"
12
+ # The descMetadata dsid is a Hydra convention for a datastream with descriptive metadata contents, like MODS or Dublin Core. They especially encourage MODS.
13
+ # The rightsMetadata dsid is also a convention provided by the Hydra Common Metadata "content model"
12
14
  #
13
15
  # For more info on the Hydra conventions, see the documentation on "Common Metadata content model" in https://wiki.duraspace.org/display/hydra/Hydra+content+models+and+disseminators
14
16
  # Note that on the wiki, "content model" is often used to refer to Fedora CModels and/or abstract/notional models. The Common Metadata content model is an example of this.
@@ -1,7 +1,7 @@
1
1
  module ActiveFedora
2
2
  module SemanticNode
3
3
  include MediaShelfClassLevelInheritableAttributes
4
- ms_inheritable_attributes :class_relationships, :internal_uri, :class_named_relationships_desc
4
+ ms_inheritable_attributes :class_relationships, :internal_uri
5
5
 
6
6
  attr_accessor :internal_uri, :named_relationship_desc, :relationships_are_dirty, :load_from_solr
7
7
 
@@ -442,7 +442,54 @@ module ActiveFedora
442
442
  end
443
443
  xml.to_s
444
444
  end
445
-
445
+
446
+ # Returns a solr query for retrieving objects specified in a relationship.
447
+ # It enables the use of query_params defined within a relationship to attach a query filter
448
+ # on top of just the predicate being used.
449
+ # Instead of this method you can also use the helper method
450
+ # [relationship_name]_query, i.e. method "parts_query" for relationship "parts".
451
+ # @param [String] The name of the relationship defined in the model
452
+ # @return [String]
453
+ # @example
454
+ # Class SampleAFObjRelationshipQueryParam < ActiveFedora::Base
455
+ # #points to all parents linked via is_member_of
456
+ # has_relationship "parents", :is_member_of
457
+ # #returns only parents that have a level value set to "series"
458
+ # has_relationship "series_parents", :is_member_of, :query_params=>{:q=>{"level_t"=>"series"}}
459
+ # end
460
+ # s = SampleAFObjRelationshipQueryParam.new
461
+ # obj = ActiveFedora::Base.new
462
+ # s.parents_append(obj)
463
+ # s.series_parents_query
464
+ # #=> "(id:changeme\\:13020 AND level_t:series)"
465
+ # SampleAFObjRelationshipQueryParam.named_relationship_query("series_parents")
466
+ # #=> "(id:changeme\\:13020 AND level_t:series)"
467
+ def named_relationship_query(relationship_name)
468
+ query = ""
469
+ if self.class.is_bidirectional_relationship?(relationship_name)
470
+ id_array = []
471
+ predicate = outbound_named_relationship_predicates["#{relationship_name}_outbound"]
472
+ if !outbound_relationships[predicate].nil?
473
+ outbound_relationships[predicate].each do |rel|
474
+ id_array << rel.gsub("info:fedora/", "")
475
+ end
476
+ end
477
+ query = self.class.bidirectional_named_relationship_query(pid,relationship_name,id_array)
478
+ elsif outbound_relationship_names.include?(relationship_name)
479
+ id_array = []
480
+ predicate = outbound_named_relationship_predicates[relationship_name]
481
+ if !outbound_relationships[predicate].nil?
482
+ outbound_relationships[predicate].each do |rel|
483
+ id_array << rel.gsub("info:fedora/", "")
484
+ end
485
+ end
486
+ query = self.class.outbound_named_relationship_query(relationship_name,id_array)
487
+ elsif inbound_relationship_names.include?(relationship_name)
488
+ query = self.class.inbound_named_relationship_query(pid,relationship_name)
489
+ end
490
+ query
491
+ end
492
+
446
493
  module ClassMethods
447
494
 
448
495
  # Allows for a relationship to be treated like any other attribute of a model class. You define
@@ -452,7 +499,10 @@ module ActiveFedora
452
499
  # class AudioRecord < ActiveFedora::Base
453
500
  #
454
501
  # has_relationship "oral_history", :has_part, :inbound=>true, :type=>OralHistory
502
+ # # returns all similar audio
455
503
  # has_relationship "similar_audio", :has_part, :type=>AudioRecord
504
+ # #returns only similar audio with format wav
505
+ # has_relationship "similar_audio_wav", :has_part, :query_params=>{:q=>"format_t"=>"wav"}
456
506
  #
457
507
  # The first two parameters are required:
458
508
  # name: relationship name
@@ -461,6 +511,7 @@ module ActiveFedora
461
511
  # possible parameters
462
512
  # :inbound => if true loads an external relationship via Solr (defaults to false)
463
513
  # :type => The type of model to use when instantiated an object from the pid in this relationship (defaults to ActiveFedora::Base)
514
+ # :query_params => Additional filters to be attached via a solr query (currently only :q implemented)
464
515
  #
465
516
  # If inbound is true it expects the relationship to be defined by another object's RELS-EXT
466
517
  # and to load that relationship from Solr. Otherwise, if inbound is true the relationship is stored in
@@ -472,22 +523,24 @@ module ActiveFedora
472
523
  # For the oral_history relationship in the example above the following helper methods are created:
473
524
  # oral_history: returns array of OralHistory objects that have this AudioRecord with predicate :has_part
474
525
  # oral_history_ids: Return array of pids for OralHistory objects that have this AudioRecord with predicate :has_part
526
+ # oral_history_query: Return solr query that can be used to retrieve related objects as solr documents
475
527
  #
476
528
  # For the outbound relationship "similar_audio" there are two additional methods to append and remove objects from that relationship
477
529
  # since it is managed internally:
478
530
  # similar_audio: Return array of AudioRecord objects that have been added to similar_audio relationship
479
531
  # similar_audio_ids: Return array of AudioRecord object pids that have been added to similar_audio relationship
532
+ # similar_audio_query: Return solr query that can be used to retrieve related objects as solr documents
480
533
  # similar_audio_append: Add an AudioRecord object to the similar_audio relationship
481
534
  # similar_audio_remove: Remove an AudioRecord from the similar_audio relationship
482
535
  def has_relationship(name, predicate, opts = {})
483
536
  opts = {:singular => nil, :inbound => false}.merge(opts)
484
537
  if opts[:inbound] == true
485
- raise "Duplicate use of predicate for named inbound relationship not allowed" if named_predicate_exists_with_different_name?(:inbound,name,predicate)
538
+ #raise "Duplicate use of predicate for named inbound relationship not allowed" if named_predicate_exists_with_different_name?(:inbound,name,predicate)
486
539
  register_named_relationship(:inbound, name, predicate, opts)
487
540
  register_predicate(:inbound, predicate)
488
541
  create_inbound_relationship_finders(name, predicate, opts)
489
542
  else
490
- raise "Duplicate use of predicate for named outbound relationship not allowed" if named_predicate_exists_with_different_name?(:self,name,predicate)
543
+ #raise "Duplicate use of predicate for named outbound relationship not allowed" if named_predicate_exists_with_different_name?(:self,name,predicate)
491
544
  register_named_relationship(:self, name, predicate, opts)
492
545
  register_predicate(:self, predicate)
493
546
  create_named_relationship_methods(name)
@@ -562,6 +615,160 @@ module ActiveFedora
562
615
  opts.merge!({:predicate=>predicate})
563
616
  named_relationships_desc[subject][name] = opts
564
617
  end
618
+
619
+ # Returns a solr query for retrieving objects specified in an outbound relationship.
620
+ # This method is mostly used by internal method calls.
621
+ # It enables the use of query_params defined within a relationship to attach a query filter
622
+ # on top of just the predicate being used. Because it is static it
623
+ # needs the pids defined within RELS-EXT for this relationship to be passed in.
624
+ # If you are calling this method directly to get the query you should use the
625
+ # ActiveFedora::SemanticNode.named_relationship_query instead or use the helper method
626
+ # [relationship_name]_query, i.e. method "parts_query" for relationship "parts". This
627
+ # method would only be called directly if you had something like an array of outbound pids
628
+ # already in something like a solr document for object that has these relationships.
629
+ # @param [String] The name of the relationship defined in the model
630
+ # @param [Array] An array of pids to include in the query
631
+ # @return [String]
632
+ # @example
633
+ # Class SampleAFObjRelationshipQueryParam < ActiveFedora::Base
634
+ # #points to all parents linked via is_member_of
635
+ # has_relationship "parents", :is_member_of
636
+ # #returns only parents that have a level value set to "series"
637
+ # has_relationship "series_parents", :is_member_of, :query_params=>{:q=>{"level_t"=>"series"}}
638
+ # end
639
+ # s = SampleAFObjRelationshipQueryParam.new
640
+ # obj = ActiveFedora::Base.new
641
+ # s.series_parents_append(obj)
642
+ # s.series_parents_query
643
+ # #=> "(id:changeme\\:13020 AND level_t:series)"
644
+ # SampleAFObjRelationshipQueryParam.outbound_named_relationship_query("series_parents",["id:changeme:13020"])
645
+ # #=> "(id:changeme\\:13020 AND level_t:series)"
646
+ def outbound_named_relationship_query(relationship_name,outbound_pids)
647
+ query = ActiveFedora::SolrService.construct_query_for_pids(outbound_pids)
648
+ subject = :self
649
+ if named_relationships_desc.has_key?(subject) && named_relationships_desc[subject].has_key?(relationship_name) && named_relationships_desc[subject][relationship_name].has_key?(:query_params)
650
+ query_params = format_query_params(named_relationships_desc[subject][relationship_name][:query_params])
651
+ if query_params[:q]
652
+ unless query.empty?
653
+ #substitute in the filter query for each pid so that it is applied to each in the query
654
+ query.sub!(/OR /,"AND #{query_params[:q]}) OR (")
655
+ #add opening parenthesis for first case
656
+ query = "(" + query
657
+ #add AND filter case for last element as well since no 'OR' following it
658
+ query << " AND #{query_params[:q]})"
659
+ else
660
+ query = query_params[:q]
661
+ end
662
+ end
663
+ end
664
+ query
665
+ end
666
+
667
+ # Returns a solr query for retrieving objects specified in an inbound relationship.
668
+ # This method is mostly used by internal method calls.
669
+ # It enables the use of query_params defined within a relationship to attach a query filter
670
+ # on top of just the predicate being used. Because it is static it
671
+ # needs the pid of the object that has the inbound relationships passed in.
672
+ # If you are calling this method directly to get the query you should use the
673
+ # ActiveFedora::SemanticNode.named_relationship_query instead or use the helper method
674
+ # [relationship_name]_query, i.e. method "parts_query" for relationship "parts". This
675
+ # method would only be called directly if you were working only with Solr and already
676
+ # had the pid for the object in something like a solr document.
677
+ # @param [String] The pid for the object that has these inbound relationships
678
+ # @param [String] The name of the relationship defined in the model
679
+ # @return [String]
680
+ # @example
681
+ # Class SampleAFObjRelationshipQueryParam < ActiveFedora::Base
682
+ # #returns all parts
683
+ # has_relationship "parts", :is_part_of, :inbound=>true
684
+ # #returns only parts that have level to "series"
685
+ # has_relationship "series_parts", :is_part_of, :inbound=>true, :query_params=>{:q=>{"level_t"=>"series"}}
686
+ # end
687
+ # s = SampleAFObjRelationshipQueryParam.new
688
+ # s.pid
689
+ # #=> id:changeme:13020
690
+ # s.series_parts_query
691
+ # #=> "is_part_of_s:info\\:fedora/changeme\\:13021 AND level_t:series"
692
+ # SampleAFObjRelationshipQueryParam.inbound_named_relationship_query(s.pid,"series_parts")
693
+ # #=> "is_part_of_s:info\\:fedora/changeme\\:13021 AND level_t:series"
694
+ def inbound_named_relationship_query(pid,relationship_name)
695
+ query = ""
696
+ subject = :inbound
697
+ if named_relationships_desc.has_key?(subject) && named_relationships_desc[subject].has_key?(relationship_name)
698
+ predicate = named_relationships_desc[subject][relationship_name][:predicate]
699
+ internal_uri = "info:fedora/#{pid}"
700
+ escaped_uri = internal_uri.gsub(/(:)/, '\\:')
701
+ query = "#{predicate}_s:#{escaped_uri}"
702
+ if named_relationships_desc.has_key?(subject) && named_relationships_desc[subject].has_key?(relationship_name) && named_relationships_desc[subject][relationship_name].has_key?(:query_params)
703
+ query_params = format_query_params(named_relationships_desc[subject][relationship_name][:query_params])
704
+ if query_params[:q]
705
+ query << " AND " unless query.empty?
706
+ query << query_params[:q]
707
+ end
708
+ end
709
+ end
710
+ query
711
+ end
712
+
713
+ # Returns a solr query for retrieving objects specified in a bidirectional relationship.
714
+ # This method is mostly used by internal method calls.
715
+ # It enables the use of query_params defined within a relationship to attach a query filter
716
+ # on top of just the predicate being used. Because it is static it
717
+ # needs the pids defined within RELS-EXT for the outbound relationship as well as the pid of the
718
+ # object for the inbound portion of the relationship.
719
+ # If you are calling this method directly to get the query you should use the
720
+ # ActiveFedora::SemanticNode.named_relationship_query instead or use the helper method
721
+ # [relationship_name]_query, i.e. method "bi_parts_query" for relationship "bi_parts". This
722
+ # method would only be called directly if you had something like an array of outbound pids
723
+ # already in something like a solr document for object that has these relationships.
724
+ # @param [String] The pid for the object that has these inbound relationships
725
+ # @param [String] The name of the relationship defined in the model
726
+ # @param [Array] An array of pids to include in the query
727
+ # @return [String]
728
+ # @example
729
+ # Class SampleAFObjRelationshipQueryParam < ActiveFedora::Base
730
+ # has_bidirectional_relationship "bi_series_parts", :has_part, :is_part_of, :query_params=>{:q=>{"level_t"=>"series"}}
731
+ # end
732
+ # s = SampleAFObjRelationshipQueryParam.new
733
+ # obj = ActiveFedora::Base.new
734
+ # s.bi_series_parts_append(obj)
735
+ # s.pid
736
+ # #=> "changeme:13025"
737
+ # obj.pid
738
+ # #=> id:changeme:13026
739
+ # s.bi_series_parts_query
740
+ # #=> "(id:changeme\\:13026 AND level_t:series) OR (is_part_of_s:info\\:fedora/changeme\\:13025 AND level_t:series)"
741
+ # SampleAFObjRelationshipQueryParam.bidirectional_named_relationship_query(s.pid,"series_parents",["id:changeme:13026"])
742
+ # #=> "(id:changeme\\:13026 AND level_t:series) OR (is_part_of_s:info\\:fedora/changeme\\:13025 AND level_t:series)"
743
+ def bidirectional_named_relationship_query(pid,relationship_name,outbound_pids)
744
+ outbound_named_relationship_query("#{relationship_name}_outbound",outbound_pids) + " OR (" + inbound_named_relationship_query(pid,"#{relationship_name}_inbound") + ")"
745
+ end
746
+
747
+ # This will transform and encode any query_params defined in a relationship method to properly escape special characters
748
+ # and format strings such as query string properly for a solr query
749
+ # @param [Hash] The has of expected query params (including at least :q)
750
+ # @return [String]
751
+ def format_query_params(query_params)
752
+ if query_params && query_params[:q]
753
+ add_query = ""
754
+ if query_params[:q].is_a? Hash
755
+ query_params[:q].keys.each_with_index do |key,index|
756
+ add_query << " AND " if index > 0
757
+ add_query << "#{key}:#{query_params[:q][key].gsub(/:/, '\\\\:')}"
758
+ end
759
+ elsif !query_params[:q].empty?
760
+ add_query = "#{query_params[:q]}"
761
+ end
762
+ query_params[:q] = add_query unless add_query.empty?
763
+ query_params
764
+ end
765
+ end
766
+
767
+ #Tests if the relationship name passed is in bidirectional
768
+ # @return [Boolean]
769
+ def is_bidirectional_relationship?(relationship_name)
770
+ named_relationships_desc[:self]["#{relationship_name}_outbound"] && named_relationships_desc[:inbound]["#{relationship_name}_inbound"]
771
+ end
565
772
 
566
773
  # ** EXPERIMENTAL **
567
774
  #
@@ -601,8 +808,8 @@ module ActiveFedora
601
808
  class_eval <<-END
602
809
  def #{name}(opts={})
603
810
  opts = {:rows=>25}.merge(opts)
604
- escaped_uri = self.internal_uri.gsub(/(:)/, '\\:')
605
- solr_result = SolrService.instance.conn.query("#{predicate}_s:\#{escaped_uri}", :rows=>opts[:rows])
811
+ query = self.class.inbound_named_relationship_query(self.pid,"#{name}")
812
+ solr_result = SolrService.instance.conn.query(query, :rows=>opts[:rows])
606
813
  if opts[:response_format] == :solr
607
814
  return solr_result
608
815
  else
@@ -625,8 +832,18 @@ module ActiveFedora
625
832
  def #{name}_from_solr
626
833
  #{name}(:response_format => :load_from_solr)
627
834
  end
835
+ def #{name}_solr_docs
836
+ #{name}(:response_format => :solr)
837
+ end
838
+ def #{name}_query
839
+ named_relationship_query("#{name}")
840
+ end
628
841
  END
629
842
  end
843
+
844
+ def relationship_has_query_params?(subject, relationship_name)
845
+ named_relationships_desc.has_key?(subject) && named_relationships_desc[subject].has_key?(relationship_name) && named_relationships_desc[subject][relationship_name].has_key?(:query_params)
846
+ end
630
847
 
631
848
  def create_outbound_relationship_finders(name, predicate, opts = {})
632
849
  class_eval <<-END
@@ -637,13 +854,20 @@ module ActiveFedora
637
854
  id_array << rel.gsub("info:fedora/", "")
638
855
  end
639
856
  end
640
- if opts[:response_format] == :id_array
857
+
858
+ if opts[:response_format] == :id_array && !self.class.relationship_has_query_params?(:self,"#{name}")
641
859
  return id_array
642
860
  else
643
- query = ActiveFedora::SolrService.construct_query_for_pids(id_array)
861
+ query = self.class.outbound_named_relationship_query("#{name}",id_array)
644
862
  solr_result = SolrService.instance.conn.query(query)
645
863
  if opts[:response_format] == :solr
646
864
  return solr_result
865
+ elsif opts[:response_format] == :id_array
866
+ id_array = []
867
+ solr_result.hits.each do |hit|
868
+ id_array << hit[SOLR_DOCUMENT_ID]
869
+ end
870
+ return id_array
647
871
  elsif opts[:response_format] == :load_from_solr || self.load_from_solr
648
872
  return ActiveFedora::SolrService.reify_solr_results(solr_result,{:load_from_solr=>true})
649
873
  else
@@ -657,9 +881,15 @@ module ActiveFedora
657
881
  def #{name}_from_solr
658
882
  #{name}(:response_format => :load_from_solr)
659
883
  end
884
+ def #{name}_solr_docs
885
+ #{name}(:response_format => :solr)
886
+ end
887
+ def #{name}_query
888
+ named_relationship_query("#{name}")
889
+ end
660
890
  END
661
891
  end
662
-
892
+
663
893
  # Generates relationship finders for predicates that point in both directions
664
894
  # and registers predicate relationships for each direction.
665
895
  #
@@ -680,12 +910,15 @@ module ActiveFedora
680
910
  def #{name}(opts={})
681
911
  opts = {:rows=>25}.merge(opts)
682
912
  if opts[:response_format] == :solr || opts[:response_format] == :load_from_solr
683
- escaped_uri = self.internal_uri.gsub(/(:)/, '\\:')
684
- query = "#{inbound_predicate}_s:\#{escaped_uri}"
685
-
686
- outbound_id_array = #{outbound_method_name}(:response_format=>:id_array)
687
- query = query + " OR " + ActiveFedora::SolrService.construct_query_for_pids(outbound_id_array)
688
-
913
+ outbound_id_array = []
914
+ predicate = outbound_named_relationship_predicates["#{name}_outbound"]
915
+ if !outbound_relationships[predicate].nil?
916
+ outbound_relationships[predicate].each do |rel|
917
+ outbound_id_array << rel.gsub("info:fedora/", "")
918
+ end
919
+ end
920
+ #outbound_id_array = #{outbound_method_name}(:response_format=>:id_array)
921
+ query = self.class.bidirectional_named_relationship_query(self.pid,"#{name}",outbound_id_array)
689
922
  solr_result = SolrService.instance.conn.query(query, :rows=>opts[:rows])
690
923
 
691
924
  if opts[:response_format] == :solr
@@ -706,6 +939,12 @@ module ActiveFedora
706
939
  def #{name}_from_solr
707
940
  #{name}(:response_format => :load_from_solr)
708
941
  end
942
+ def #{name}_solr_docs
943
+ #{name}(:response_format => :solr)
944
+ end
945
+ def #{name}_query
946
+ named_relationship_query("#{name}")
947
+ end
709
948
  END
710
949
  end
711
950
 
@@ -1,3 +1,3 @@
1
1
  module ActiveFedora
2
- VERSION = "2.3.0"
2
+ VERSION = "2.3.1"
3
3
  end
@@ -1,13 +1,13 @@
1
1
  development:
2
2
  fedora:
3
- url: http://fedoraAdmin:fedoraAdmin@testhost.com:8983/fedora
3
+ url: http://fedoraAdmin:fedoraAdmin@localhost:8983/fedora
4
4
  solr:
5
- url: http://testhost.com:8983/solr/development
5
+ url: http://localhost:8983/solr/development
6
6
  test:
7
7
  fedora:
8
- url: http://fedoraAdmin:fedoraAdmin@testhost.com:8983/fedora
8
+ url: http://fedoraAdmin:fedoraAdmin@localhost:8983/fedora
9
9
  solr:
10
- url: http://testhost.com:8983/solr/development
10
+ url: http://localhost:8983/solr/development
11
11
  production:
12
12
  fedora:
13
13
  url: http://fedoraAdmin:fedoraAdmin@testhost.com:8080/fedora
@@ -20,7 +20,8 @@ describe ActiveFedora::NokogiriDatastream do
20
20
  m.field 'collection', :string
21
21
  end
22
22
  end
23
-
23
+
24
+ RAILS_ENV='development'
24
25
  @pid = "hydrangea:fixture_mods_article1"
25
26
  @test_solr_object = HydrangeaArticle2.load_instance_from_solr(@pid)
26
27
  @test_object = HydrangeaArticle2.load_instance(@pid)
@@ -13,6 +13,15 @@ describe ActiveFedora::SemanticNode do
13
13
  class SNSpecModel < ActiveFedora::Base
14
14
  has_relationship("parts", :is_part_of, :inbound => true)
15
15
  has_relationship("containers", :is_member_of)
16
+ has_bidirectional_relationship("bi_containers", :is_member_of, :has_member)
17
+ end
18
+ class SpecNodeQueryParam < ActiveFedora::Base
19
+ has_relationship("parts", :is_part_of, :inbound => true)
20
+ has_relationship("special_parts", :is_part_of, :inbound => true, :query_params=>{:q=>{"has_model_s"=>"info:fedora/SpecialPart"}})
21
+ has_relationship("containers", :is_member_of)
22
+ has_relationship("special_containers", :is_member_of, :query_params=>{:q=>{"has_model_s"=>"info:fedora/SpecialContainer"}})
23
+ has_bidirectional_relationship("bi_containers", :is_member_of, :has_member)
24
+ has_bidirectional_relationship("bi_special_containers", :is_member_of, :has_member, :query_params=>{:q=>{"has_model_s"=>"info:fedora/SpecialContainer"}})
16
25
  end
17
26
 
18
27
  @test_object = SNSpecModel.new
@@ -25,24 +34,89 @@ describe ActiveFedora::SemanticNode do
25
34
  @part2.add_relationship(:is_part_of, @test_object)
26
35
  @part2.save
27
36
 
28
-
29
37
  @container1 = ActiveFedora::Base.new()
30
38
  @container1.save
31
39
  @container2 = ActiveFedora::Base.new()
32
40
  @container2.save
41
+ @container3 = ActiveFedora::Base.new()
42
+ @container3.save
33
43
 
34
44
  @test_object.add_relationship(:is_member_of, @container1)
35
45
  @test_object.add_relationship(:is_member_of, @container2)
36
46
  @test_object.save
47
+
48
+ @special_container = ActiveFedora::Base.new()
49
+ @special_container.add_relationship(:has_model,"SpecialContainer")
50
+ @special_container.save
51
+
52
+ #even though adding container3 and special container, it should only include special_container when returning via named finder methods
53
+ #also should only return special part similarly
54
+ @test_object_query = SpecNodeQueryParam.new
55
+ @test_object_query.add_relationship(:is_member_of, @container3)
56
+ @test_object_query.add_relationship(:is_member_of, @special_container)
57
+ @test_object_query.save
58
+
59
+ @special_container2 = ActiveFedora::Base.new()
60
+ @special_container2.add_relationship(:has_model,"SpecialContainer")
61
+ @special_container2.add_relationship(:has_member,@test_object_query.pid)
62
+ @special_container2.save
63
+
64
+ @part3 = ActiveFedora::Base.new()
65
+ @part3.add_relationship(:is_part_of, @test_object_query)
66
+ @part3.save
67
+
68
+ @special_part = ActiveFedora::Base.new()
69
+ @special_part.add_relationship(:has_model,"SpecialPart")
70
+ @special_part.add_relationship(:is_part_of, @test_object_query)
71
+ @special_part.save
72
+
37
73
  end
38
74
 
39
75
  after(:all) do
76
+ begin
40
77
  @part1.delete
78
+ rescue
79
+ end
80
+ begin
41
81
  @part2.delete
82
+ rescue
83
+ end
84
+ begin
85
+ @part3.delete
86
+ rescue
87
+ end
88
+ begin
42
89
  @container1.delete
90
+ rescue
91
+ end
92
+ begin
43
93
  @container2.delete
94
+ rescue
95
+ end
96
+ begin
97
+ @container3.delete
98
+ rescue
99
+ end
100
+ begin
44
101
  @test_object.delete
45
-
102
+ rescue
103
+ end
104
+ begin
105
+ @test_object_query.delete
106
+ rescue
107
+ end
108
+ begin
109
+ @special_part.delete
110
+ rescue
111
+ end
112
+ begin
113
+ @special_container.delete
114
+ rescue
115
+ end
116
+ begin
117
+ @special_container2.delete
118
+ rescue
119
+ end
46
120
  Object.send(:remove_const, :SNSpecModel)
47
121
 
48
122
  end
@@ -74,6 +148,73 @@ describe ActiveFedora::SemanticNode do
74
148
  id.should satisfy {|id| id == @part1.pid || @part2.pid}
75
149
  end
76
150
  end
151
+ it "should return an array of Base objects with some filtered out if using query params" do
152
+ @test_object_query.special_parts_ids.should == [@special_part.pid]
153
+ end
154
+
155
+ it "should return an array of all Base objects with relationship if not using query params" do
156
+ @test_object_query.parts_ids.size.should == 2
157
+ @test_object_query.parts_ids.include?(@special_part.pid).should == true
158
+ @test_object_query.parts_ids.include?(@part3.pid).should == true
159
+ end
160
+
161
+ it "should return a solr query for an inbound relationship" do
162
+ @test_object_query.special_parts_query.should == "#{@test_object_query.named_relationship_predicates[:inbound]['special_parts']}_s:#{@test_object_query.internal_uri.gsub(/(:)/, '\\:')} AND has_model_s:info\\:fedora/SpecialPart"
163
+ end
164
+ end
165
+
166
+ describe "inbound named relationship query" do
167
+ it "should return a properly formatted query for a relationship that has a query param defined" do
168
+ SpecNodeQueryParam.inbound_named_relationship_query(@test_object_query.pid,"special_parts").should == "#{@test_object_query.named_relationship_predicates[:inbound]['special_parts']}_s:#{@test_object_query.internal_uri.gsub(/(:)/, '\\:')} AND has_model_s:info\\:fedora/SpecialPart"
169
+ end
170
+
171
+ it "should return a properly formatted query for a relationship that does not have a query param defined" do
172
+ SpecNodeQueryParam.inbound_named_relationship_query(@test_object_query.pid,"parts").should == "is_part_of_s:#{@test_object_query.internal_uri.gsub(/(:)/, '\\:')}"
173
+ end
174
+ end
175
+
176
+ describe "outbound named relationship query" do
177
+ it "should return a properly formatted query for a relationship that has a query param defined" do
178
+ expected_string = ""
179
+ @test_object_query.containers_ids.each_with_index do |id,index|
180
+ expected_string << " OR " if index > 0
181
+ expected_string << "(id:" + id.gsub(/(:)/, '\\:') + " AND has_model_s:info\\:fedora/SpecialContainer)"
182
+ end
183
+ SpecNodeQueryParam.outbound_named_relationship_query("special_containers",@test_object_query.containers_ids).should == expected_string
184
+ end
185
+
186
+ it "should return a properly formatted query for a relationship that does not have a query param defined" do
187
+ expected_string = ""
188
+ @test_object_query.containers_ids.each_with_index do |id,index|
189
+ expected_string << " OR " if index > 0
190
+ expected_string << "id:" + id.gsub(/(:)/, '\\:')
191
+ end
192
+ SpecNodeQueryParam.outbound_named_relationship_query("containers",@test_object_query.containers_ids).should == expected_string
193
+ end
194
+ end
195
+
196
+ describe "bidirectional named relationship query" do
197
+ it "should return a properly formatted query for a relationship that has a query param defined" do
198
+ expected_string = ""
199
+ @test_object_query.bi_containers_outbound_ids.each_with_index do |id,index|
200
+ expected_string << " OR " if index > 0
201
+ expected_string << "(id:" + id.gsub(/(:)/, '\\:') + " AND has_model_s:info\\:fedora/SpecialContainer)"
202
+ end
203
+ expected_string << " OR "
204
+ expected_string << "(#{@test_object_query.named_relationship_predicates[:inbound]['bi_special_containers_inbound']}_s:#{@test_object_query.internal_uri.gsub(/(:)/, '\\:')} AND has_model_s:info\\:fedora/SpecialContainer)"
205
+ SpecNodeQueryParam.bidirectional_named_relationship_query(@test_object_query.pid,"bi_special_containers",@test_object_query.bi_containers_outbound_ids).should == expected_string
206
+ end
207
+
208
+ it "should return a properly formatted query for a relationship that does not have a query param defined" do
209
+ expected_string = ""
210
+ @test_object_query.bi_containers_outbound_ids.each_with_index do |id,index|
211
+ expected_string << " OR " if index > 0
212
+ expected_string << "id:" + id.gsub(/(:)/, '\\:')
213
+ end
214
+ expected_string << " OR "
215
+ expected_string << "(#{@test_object_query.named_relationship_predicates[:inbound]['bi_special_containers_inbound']}_s:#{@test_object_query.internal_uri.gsub(/(:)/, '\\:')})"
216
+ SpecNodeQueryParam.bidirectional_named_relationship_query(@test_object_query.pid,"bi_containers",@test_object_query.bi_containers_outbound_ids).should == expected_string
217
+ end
77
218
  end
78
219
 
79
220
  describe "outbound relationship finders" do
@@ -90,5 +231,121 @@ describe ActiveFedora::SemanticNode do
90
231
  id.should satisfy {|id| id == @container1.pid || @container2.pid}
91
232
  end
92
233
  end
234
+
235
+ it "should return an array of Base objects with some filtered out if using query params" do
236
+ @test_object_query.special_containers_ids.size.should == 1
237
+ @test_object_query.special_containers_ids.include?(@container3.pid).should == false
238
+ @test_object_query.special_containers_ids.include?(@special_container.pid).should == true
239
+ end
240
+
241
+ it "should return an array of all Base objects with relationship if not using query params" do
242
+ @test_object_query.containers_ids.size.should == 2
243
+ @test_object_query.containers_ids.include?(@special_container2.pid).should == false
244
+ @test_object_query.containers_ids.include?(@special_container.pid).should == true
245
+ @test_object_query.containers_ids.include?(@container3.pid).should == true
246
+ end
247
+
248
+ it "should return a solr query for an outbound relationship" do
249
+ expected_string = ""
250
+ @test_object_query.containers_ids.each_with_index do |id,index|
251
+ expected_string << " OR " if index > 0
252
+ expected_string << "(id:" + id.gsub(/(:)/, '\\:') + " AND has_model_s:info\\:fedora/SpecialContainer)"
253
+ end
254
+ @test_object_query.special_containers_query.should == expected_string
255
+ end
93
256
  end
257
+
258
+ describe "bidirectional relationship finders" do
259
+ it "should return an array of Base objects" do
260
+ containers = @test_object.bi_containers
261
+ containers.length.should > 0
262
+ containers.each do |container|
263
+ container.should be_kind_of(ActiveFedora::Base)
264
+ end
265
+ end
266
+ it "_ids should return an array of pids" do
267
+ ids = @test_object.bi_containers_ids
268
+ ids.size.should == 2
269
+ ids.each do |id|
270
+ id.should satisfy {|id| id == @container1.pid || @container2.pid}
271
+ end
272
+ end
273
+
274
+ it "should return an array of Base objects with some filtered out if using query params" do
275
+ ids = @test_object_query.bi_special_containers_ids
276
+ ids.size.should == 2
277
+ ids.each do |id|
278
+ id.should satisfy {|id| id == @special_container.pid || @special_container2.pid}
279
+ end
280
+ end
281
+
282
+ it "should return an array of all Base objects with relationship if not using query params" do
283
+ ids = @test_object_query.bi_containers_ids
284
+ ids.size.should == 3
285
+ ids.each do |id|
286
+ id.should satisfy {|id| id == @special_container.pid || @special_container2.pid || @container3.pid}
287
+ end
288
+ end
289
+
290
+ it "should return a solr query for a bidirectional relationship" do
291
+ expected_string = ""
292
+ @test_object_query.bi_containers_outbound_ids.each_with_index do |id,index|
293
+ expected_string << " OR " if index > 0
294
+ expected_string << "(id:" + id.gsub(/(:)/, '\\:') + " AND has_model_s:info\\:fedora/SpecialContainer)"
295
+ end
296
+ expected_string << " OR "
297
+ expected_string << "(#{@test_object_query.named_relationship_predicates[:inbound]['bi_special_containers_inbound']}_s:#{@test_object_query.internal_uri.gsub(/(:)/, '\\:')} AND has_model_s:info\\:fedora/SpecialContainer)"
298
+ @test_object_query.bi_special_containers_query.should == expected_string
299
+ end
300
+ end
301
+
302
+ describe "named_relationship_query" do
303
+ it "should return correct query for a bidirectional relationship with query params" do
304
+ expected_string = ""
305
+ @test_object_query.bi_containers_outbound_ids.each_with_index do |id,index|
306
+ expected_string << " OR " if index > 0
307
+ expected_string << "(id:" + id.gsub(/(:)/, '\\:') + " AND has_model_s:info\\:fedora/SpecialContainer)"
308
+ end
309
+ expected_string << " OR "
310
+ expected_string << "(#{@test_object_query.named_relationship_predicates[:inbound]['bi_special_containers_inbound']}_s:#{@test_object_query.internal_uri.gsub(/(:)/, '\\:')} AND has_model_s:info\\:fedora/SpecialContainer)"
311
+ @test_object_query.named_relationship_query("bi_special_containers").should == expected_string
312
+ end
313
+
314
+ it "should return correct query for a bidirectional relationship without query params" do
315
+ expected_string = ""
316
+ @test_object_query.bi_containers_outbound_ids.each_with_index do |id,index|
317
+ expected_string << " OR " if index > 0
318
+ expected_string << "id:" + id.gsub(/(:)/, '\\:')
319
+ end
320
+ expected_string << " OR "
321
+ expected_string << "(#{@test_object_query.named_relationship_predicates[:inbound]['bi_special_containers_inbound']}_s:#{@test_object_query.internal_uri.gsub(/(:)/, '\\:')})"
322
+ @test_object_query.named_relationship_query("bi_containers").should == expected_string
323
+ end
324
+
325
+ it "should return a properly formatted query for an outbound relationship that has a query param defined" do
326
+ expected_string = ""
327
+ @test_object_query.containers_ids.each_with_index do |id,index|
328
+ expected_string << " OR " if index > 0
329
+ expected_string << "(id:" + id.gsub(/(:)/, '\\:') + " AND has_model_s:info\\:fedora/SpecialContainer)"
330
+ end
331
+ @test_object_query.named_relationship_query("special_containers").should == expected_string
332
+ end
333
+
334
+ it "should return a properly formatted query for an outbound relationship that does not have a query param defined" do
335
+ expected_string = ""
336
+ @test_object_query.containers_ids.each_with_index do |id,index|
337
+ expected_string << " OR " if index > 0
338
+ expected_string << "id:" + id.gsub(/(:)/, '\\:')
339
+ end
340
+ @test_object_query.named_relationship_query("containers").should == expected_string
341
+ end
342
+
343
+ it "should return a properly formatted query for an inbound relationship that has a query param defined" do
344
+ @test_object_query.named_relationship_query("special_parts").should == "#{@test_object_query.named_relationship_predicates[:inbound]['special_parts']}_s:#{@test_object_query.internal_uri.gsub(/(:)/, '\\:')} AND has_model_s:info\\:fedora/SpecialPart"
345
+ end
346
+
347
+ it "should return a properly formatted query for an inbound relationship that does not have a query param defined" do
348
+ @test_object_query.named_relationship_query("parts").should == "is_part_of_s:#{@test_object_query.internal_uri.gsub(/(:)/, '\\:')}"
349
+ end
350
+ end
94
351
  end