module ActiveFedora::SemanticNode::ClassMethods

def create_inbound_relationship_finders(name, predicate, opts = {})

def create_inbound_relationship_finders(name, predicate, opts = {})
  class_eval <<-END
  def #{name}(opts={})
    escaped_uri = self.internal_uri.gsub(/(:)/, '\\:')
    solr_result = SolrService.instance.conn.query("#{predicate}_s:\#{escaped_uri}")
    if opts[:response_format] == :solr
      return solr_result
    else
      if opts[:response_format] == :id_array
        id_array = []
        solr_result.hits.each do |hit|
          id_array << hit[SOLR_DOCUMENT_ID]
        end
        return id_array
      else
        return ActiveFedora::SolrService.reify_solr_results(solr_result)
      end
    end
  end
  def #{name}_ids
    #{name}(:response_format => :id_array)
  end 
  END
end

def create_outbound_relationship_finders(name, predicate, opts = {})

def create_outbound_relationship_finders(name, predicate, opts = {})
  class_eval <<-END
  def #{name}(opts={})
    id_array = []
    if !outbound_relationships[#{predicate.inspect}].nil? 
      outbound_relationships[#{predicate.inspect}].each do |rel|
        id_array << rel.gsub("info:fedora/", "")
      end
    end
    if opts[:response_format] == :id_array
      return id_array
    else
      query = ActiveFedora::SolrService.construct_query_for_pids(id_array)
      solr_result = SolrService.instance.conn.query(query)
      if opts[:response_format] == :solr
        return solr_result
      else
        return ActiveFedora::SolrService.reify_solr_results(solr_result)
      end
    end
  end
  def #{name}_ids
    #{name}(:response_format => :id_array)
  end
  END
end

def has_relationship(name, predicate, opts = {})

:is_member_of, :has_member, :is_part_of, :has_part
These symbols map to the uris of corresponding Fedora RDF predicates
Special Predicate Short Hand:

foo.parts
foo = Foo.new
end
relationship "container", :is_member_of
class Foo
ie.
A custom finder method will be appended based on the relationship name.
Custom Methods:
TODO:

predicate is registered under @relationships[:inbound][#{predicate}]
:self as the subject of the relationship unless :inbound => true, in which case the
Creates a key in the @relationships array for the predicate provided. Assumes
Anticipates usage of a relationship in classes that include this module
def has_relationship(name, predicate, opts = {})
  opts = {:singular => nil, :inbound => false}.merge(opts)
  opts[:inbound] == true ? register_predicate(:inbound, predicate) : register_predicate(:self, predicate) 

  if opts[:inbound] == true
    create_inbound_relationship_finders(name, predicate, opts)
  else        
    create_outbound_relationship_finders(name, predicate, opts)
  end

end

def predicate_lookup(predicate)

@throws UnregisteredPredicateError if the predicate is a symbol but is not found in the PREDICATE_MAPPINGS
If predicate is not a Symbol, returns the predicate untouched
If predicate is a symbol, looks up the predicate in the PREDICATE_MAPPINGS
def predicate_lookup(predicate)
  if predicate.class == Symbol 
    if PREDICATE_MAPPINGS.has_key?(predicate)
      return PREDICATE_MAPPINGS[predicate]
    else
      throw UnregisteredPredicateError
    end
  end
  return predicate
end

def register_predicate(subject, predicate)

def register_predicate(subject, predicate)
  register_subject(subject)
  if !relationships[subject].has_key?(predicate) 
    relationships[subject][predicate] = []
  end
end

def register_subject(subject)

def register_subject(subject)
  if !relationships.has_key?(subject) 
      relationships[subject] = {} 
  end
end

def relationships

relationships are tracked as a hash of structure {subject => {predicate => [object]}}
def relationships
  @class_relationships ||= Hash[:self => {}]
end

def relationships_to_rels_ext(pid, relationships=self.relationships)

Note: This method is implemented on SemanticNode instead of RelsExtDatastream because SemanticNode contains the relationships array
@pid
Creates a RELS-EXT datastream for insertion into a Fedora Object
def relationships_to_rels_ext(pid, relationships=self.relationships)
  starter_xml = <<-EOL
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <rdf:Description rdf:about="info:fedora/#{pid}">
    </rdf:Description>
  </rdf:RDF>
  EOL
  xml = REXML::Document.new(starter_xml)

  # Iterate through the hash of predicates, adding an element to the RELS-EXT for each "object" in the predicate's corresponding array.
  self.outbound_relationships.each do |predicate, targets_array|
    targets_array.each do |target|
      #puts ". #{predicate} #{target}"
      xml.root.elements["rdf:Description"].add_element(predicate_lookup(predicate), {"xmlns" => "info:fedora/fedora-system:def/relations-external#", "rdf:resource"=>target})
    end
  end
  xml.to_s
end