ucsdlib/damspas

View on GitHub
app/controllers/dams_resource_controller.rb

Summary

Maintainability
C
1 day
Test Coverage
require 'net/http'
require 'json'
require 'open-uri'
require 'pathname'
require 'httparty'

class DamsResourceController < ApplicationController
  include Blacklight::Catalog
  include Dams::ControllerHelper
  include CatalogHelper
  

  ##############################################################################
  # solr actions ###############################################################
  ##############################################################################
  def show
    refcon = referrer_controller request
    if params[:counter]
      # if there is a counter, update pager state & redirect to no-counter view
      logger.info "dams_resource_controller#show (#{refcon}) adding query to session and redirecting"
      session[:search][:counter] = params[:counter]
      session[:search_results] = request.referer if refcon == "catalog"
      redirect_to dams_object_path(params[:id])
      return
    else
      @blacklight_config = CatalogController.blacklight_config

      # if we were redirected from counter, setup next/prev
      controllers = ["catalog", "dams_collections", "dams_objects"]
      logger.info "dams_resource_controller#show (#{refcon}) controllers.include?(refcon)? #{controllers.include?(refcon)}"
      setup_next_and_previous_documents if controllers.include?(refcon)
    end

    # get metadata from solr
    @document = get_single_doc_via_search(1, {:q => "id:#{params[:id]}"} )
    if @document.nil?
        raise ActionController::RoutingError.new('Not Found')
    end

    # generate facet collection list for collection page only
    models = @document["active_fedora_model_ssi"]
    if models.include?("DamsAssembledCollection") || models.include?("DamsProvenanceCollection") || models.include?("DamsProvenanceCollectionPart") 
        collection_solr_params = build_params("collections_tesim:#{params[:id]}", metadata_only_fquery)
        collection_response = raw_solr(collection_solr_params)
        @metadata_only = collection_response.response['numFound'].to_i > 0
        @mix_objects = mix_objects?(params[:id], collection_response.response['numFound'].to_i)
        
        facet_collection_params = { :f=>{"collection_sim"=>"#{@document['title_tesim'].first.to_s}"}, :id=>params[:id], :rows => 0 }
        apply_gated_discovery( facet_collection_params, nil )
        @facet_collection_resp = get_search_results( facet_collection_params )
        facet_collection_names = []
        @facet_collections = @facet_collection_resp[0].facet_counts["facet_fields"]["collection_sim"]
        if !@facet_collections.nil? && @facet_collections.length > 0
            @facet_collections.each_slice(2) do |collectionName, *_|
                facet_collection_names << collectionName.strip if !collectionName.strip.eql? @document['title_tesim'].first.strip.to_s
            end
        end
        @related_collections = related_collections_map facet_collection_names
    else
      @metadata_only = metadata_display?(rights_data(@document))
    end

    @rdfxml = @document['rdfxml_ssi']
    if @rdfxml == nil
      @rdfxml = "<rdf:RDF xmlns:dams='http://library.ucsd.edu/ontology/dams#'
          xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
          rdf:about='#{Rails.configuration.id_namespace}#{params[:id]}'>
  <dams:error>content missing</dams:error>
</rdf:RDF>"
    end

    url = check_type @document
    unless url.blank?
      redirect_to url
      return
    end

    # enforce access controls
    if can?(:show, @document) || @document['discover_access_group_ssim'].include?("public")
      # find related resources
      collectionData = @document["collection_json_tesim"]
      @collectionDocArray = Array.new
      if !collectionData.nil? and collectionData.length > 0
          collectionData.each do |datum|
          collection = JSON.parse(datum)
          collectionDoc = get_single_doc_via_search(1, {:q => "id:#{collection['id']}"} )
          relatedResourceData = collectionDoc["related_resource_json_tesim"] unless collectionDoc.nil?
          if !relatedResourceData.nil?
            relatedResourceData.each do |datum|
              relatedResource = JSON.parse(datum)
              if relatedResource['type'] != "hydra-afmodel"
                @collectionDocArray << collectionDoc
                break
              end            
            end
          end
        end
      end

      find_linked_documents @document
      
      respond_to do |format|
        format.html # show.html.erb
        format.json { render json: @document }
        format.rdf { render xml: @rdfxml }
        format.nt { rdf_nt }
        format.ttl { rdf_ttl }
      end
    elsif @document['discover_access_group_ssim'].include?("public")
      respond_to do |format|
        format.html
        format.json { render json: @document }
        format.rdf { render xml: @rdfxml }
        format.nt { rdf_nt }
        format.ttl { rdf_ttl }
      end
    else
      authorize! :show, @document # 403 forbidden
    end
  end
  def find_linked_documents( document )
  end
  def redirect_other_types( document )
  end
  def dams42
    @document = get_single_doc_via_search(1, {:q => "id:#{params[:id]}"} )
    authorize! :show, @document
    params[:xsl] = "dams4.2.xsl"
    data = get_html_data params, nil
    render :xml => data, :content_type => 'application/rdf+xml'
  end 
  def data
    @document = get_single_doc_via_search(1, {:q => "id:#{params[:id]}"} )
    authorize! :show, @document
      controller_path = dams_collection_path params[:id]
    data = get_html_data params, controller_path
    render :text => data
  end 
  def rdf
    @document = get_single_doc_via_search(1, {:q => "id:#{params[:id]}"} )
    authorize! :show, @document
    params[:xsl] = "normalize.xsl"
    data = get_html_data params, nil
    render :xml => data, :content_type => 'application/rdf+xml'
  end
  def rdf_nt
    @document = get_single_doc_via_search(1, {:q => "id:#{params[:id]}"} )
    authorize! :show, @document
    data = get_data("nt")
    render :text => data, :content_type => 'application/n-triples'
  end
  def rdf_ttl
    @document = get_single_doc_via_search(1, {:q => "id:#{params[:id]}"} )
    authorize! :show, @document
    data = get_data("turtle")
    render :text => data, :content_type => 'text/turtle'
  end 
  def ezid
    @document = get_single_doc_via_search(1, {:q => "id:#{params[:id]}"} )
    authorize! :create, @document

    # mint doi
    begin
      json = dams_post "#{dams_api_path}/api/objects/#{params[:id]}/mint_doi?format=json"
      if json['statusCode'] == 200
        logger.info json['message']
        redirect_to dams_object_path(params[:id]), notice: "DOI minted, please allow a few minutes for Solr reindexing before the display is updated."
      else
        redirect_to dams_object_path(params[:id]), alert: "Minting DOI failed: #{json['message']}"
      end
    rescue Exception => e
      begin
        resp = JSON.parse( e.response.body )
        err = resp["message"]
      rescue
        err = "Error minting DOI: Unable to process server response"
      end
      redirect_to dams_object_path(params[:id]), alert: err
    end
  end

  def related_collections_map (collection_names)
    colls_map = {}
    if collection_names.count > 0
        collection_names.collect! { |name| "\"#{solr_escape(name)}\"" }
        solr_param_q = collection_names.join (' OR ')
        solr_params = { :q => "type_tesim:Collection AND title_tesim:(#{solr_param_q})", :rows => collection_names.count }
        cols_response, col_documents = get_search_results(solr_params)
        cols_response.docs.each do |doc|
            colls_map[doc['title_tesim'].first.to_s.strip] = doc['id_t'].to_s
        end
    end
    colls_map
  end

  def solr_escape (str)
    pattern = /(\+|\-|\&\&|\|\||\!|\(\)|\{\}|\[|\]|\^|\"|\~|\*|\?|\:|\\)/
    str.gsub(pattern){|match|"\\"  + match} 
  end
    
  def osf_api
    @document = get_single_doc_via_search(1, {:q => "id:#{params[:id]}"} )
    authorize! :show, @document
    data = export_to_api(@document)

    render :json => data
  end

  def osf_data
    @document = get_single_doc_via_search(1, {:q => "id:#{params[:id]}"})
    render :json => @document
  end

  def osf_delete
    @document = get_single_doc_via_search(1, q: "id:#{params[:id]}")
    authorize! :show, @document
    document = ShareNotify::PushDocument.new("http://library.ucsd.edu/dc/collection/#{params[:id]}")
    document.title = osf_title(@document)
    document.delete
    share_upload(document)
    redirect_to dams_collection_path(params[:id]), notice: 'Your record has been deleted from OSF Share.'
  end

  def osf_push
    @document = get_single_doc_via_search(1, {:q => "id:#{params[:id]}"} )
    authorize! :show, @document
    document = ShareNotify::PushDocument.new("http://library.ucsd.edu/dc/collection/#{params[:id]}")
    document.type = 'DataSet' if @document['unit_code_tesim'].first == 'rdcp'
    document.title = osf_title(@document)
    document.description = osf_description(@document)
    document.languages = osf_languages(@document)
    document.date_published = osf_date_published(@document)
    document.tags = osf_mads_fields(@document)
    document.related_agents = osf_related_agents(@document)
    document.extra = osf_extra(@document)
    osf_contributors(@document).each do |contributor|
      document.add_contributor(contributor)
    end

    if document.valid?
      share_upload(document)
      redirect_to dams_collection_path(params[:id]), notice: "Your record has been pushed to OSF Share."
    else
      redirect_to dams_collection_path(params[:id]), alert: "Your record is not valid."
    end
  end

  private
    def share_upload(document)
      @headers = {
        'Authorization' => "Bearer #{share_config.fetch('token')}",
        'Content-Type'  => 'application/vnd.api+json'
      }
      @route = "#{share_config.fetch('host')}api/v2/normalizeddata/"
      @body = ShareNotify::Graph.new(document).to_share_v2.to_json
      @response = with_timeout { HTTParty.post(@route, body: @body, headers: @headers) }
    end

    def share_config
      env = Rails.env || 'test'
      @config ||= YAML.load(ERB.new(IO.read(File.join(Rails.root, 'config', 'share_notify.yml'))).result)[env].with_indifferent_access
    end

    def with_timeout(&_block)
      Timeout.timeout(5) { yield }
    end
end