Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ResourceSync resource list capability
- Loading branch information
Showing
14 changed files
with
335 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
inherit_from: .rubocop_todo.yml | ||
|
||
AllCops: | ||
TargetRubyVersion: 2.1 | ||
DisplayCopNames: true | ||
Include: | ||
- '**/Rakefile' | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
class Sufia::ResourceSyncController < ApplicationController | ||
def source_description | ||
# Caching based on host, for multitenancy support | ||
body = Rails.cache.fetch("source_description_#{request.host}", expires_in: 1.week) do | ||
build_source_description | ||
end | ||
render body: body, content_type: 'application/xml' | ||
end | ||
|
||
def capability_list | ||
# Caching based on host, for multitenancy support | ||
body = Rails.cache.fetch("source_description_#{request.host}", expires_in: 1.week) do | ||
build_capability_list | ||
end | ||
render body: body, content_type: 'application/xml' | ||
end | ||
|
||
def resource_list | ||
# Caching based on host, for multitenancy support | ||
body = Rails.cache.fetch("source_description_#{request.host}", expires_in: 1.week) do | ||
build_resource_list | ||
end | ||
render body: body, content_type: 'application/xml' | ||
end | ||
|
||
private | ||
|
||
def build_resource_list | ||
Sufia::ResourceSync::ResourceListWriter.new(capability_list_url: sufia.capability_list_url, | ||
resource_host: request.host).write | ||
end | ||
|
||
def build_capability_list | ||
Sufia::ResourceSync::CapabilityListWriter.new(resource_list_url: sufia.resource_list_url, | ||
description_url: sufia.source_description_url).write | ||
end | ||
|
||
def build_source_description | ||
Sufia::ResourceSync::SourceDescriptionWriter.new(capability_list_url: sufia.capability_list_url).write | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
module Sufia | ||
module ResourceSync | ||
extend ActiveSupport::Autoload | ||
|
||
eager_autoload do | ||
autoload :CapabilityListWriter | ||
autoload :ResourceListWriter | ||
autoload :SourceDescriptionWriter | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
module Sufia | ||
module ResourceSync | ||
class CapabilityListWriter | ||
attr_reader :resource_list_url, :description_url | ||
def initialize(resource_list_url:, description_url:) | ||
@resource_list_url = resource_list_url | ||
@description_url = description_url | ||
end | ||
|
||
def write | ||
builder.to_xml | ||
end | ||
|
||
private | ||
|
||
def builder | ||
Nokogiri::XML::Builder.new do |xml| | ||
xml.urlset('xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9', | ||
'xmlns:rs' => 'http://www.openarchives.org/rs/terms/') do | ||
xml['rs'].ln(rel: "up", href: description_url) | ||
xml['rs'].md(capability: "capabilitylist") | ||
xml.url do | ||
xml.loc resource_list_url | ||
xml['rs'].md(capability: 'resourcelist') | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
module Sufia | ||
module ResourceSync | ||
# TODO: the big assumption I'm making here is that the repository has fewer | ||
# than 50,000 resources to list. The Sitemap protocol is limited at 50,000 | ||
# items, so if we require more than that, we must have multiple Resource | ||
# lists and add a Resource List Index to point to all of them. | ||
class ResourceListWriter | ||
attr_reader :resource_host, :capability_list_url | ||
|
||
def initialize(resource_host:, capability_list_url:) | ||
@resource_host = resource_host | ||
@capability_list_url = capability_list_url | ||
end | ||
|
||
def write | ||
builder.to_xml | ||
end | ||
|
||
private | ||
|
||
def builder(capability_list_url: 'http://example.com/dataset1/capabilitylist.xml') | ||
Nokogiri::XML::Builder.new do |xml| | ||
xml.urlset('xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9', | ||
'xmlns:rs' => 'http://www.openarchives.org/rs/terms/') do | ||
xml['rs'].ln(rel: "up", href: capability_list_url) | ||
xml['rs'].md(capability: "resourcelist", at: Time.now.utc.iso8601) | ||
build_collections(xml) | ||
build_works(xml) | ||
build_files(xml) | ||
end | ||
end | ||
end | ||
|
||
def build_collections(xml) | ||
Collection.search_in_batches(public_access) do |doc_set| | ||
build_resources(xml, doc_set) | ||
end | ||
end | ||
|
||
def build_works(xml) | ||
CurationConcerns::WorkRelation.new.search_in_batches(public_access) do |doc_set| | ||
build_resources(xml, doc_set) | ||
end | ||
end | ||
|
||
def build_files(xml) | ||
FileSet.search_in_batches(public_access) do |doc_set| | ||
build_resources(xml, doc_set) | ||
end | ||
end | ||
|
||
def build_resources(xml, doc_set) | ||
doc_set.each do |doc| | ||
build_resource(xml, doc) | ||
end | ||
end | ||
|
||
def build_resource(xml, doc) | ||
xml.url do | ||
key = doc.fetch('has_model_ssim', []).first.constantize.model_name.singular_route_key | ||
xml.loc routes.send(key + "_url", doc['id'], host: resource_host) | ||
xml.lastmod doc['system_modified_dtsi'] | ||
end | ||
end | ||
|
||
def routes | ||
Rails.application.routes.url_helpers | ||
end | ||
|
||
delegate :collection_url, to: :routes | ||
|
||
def public_access | ||
{ Hydra.config.permissions.read.group => 'public' } | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
module Sufia | ||
module ResourceSync | ||
class SourceDescriptionWriter | ||
attr_reader :capability_list_url | ||
def initialize(capability_list_url: 'http://example.com/dataset1/capabilitylist.xml') | ||
@capability_list_url = capability_list_url | ||
end | ||
|
||
def write | ||
builder.to_xml | ||
end | ||
|
||
private | ||
|
||
def builder | ||
Nokogiri::XML::Builder.new do |xml| | ||
xml.urlset('xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9', | ||
'xmlns:rs' => 'http://www.openarchives.org/rs/terms/') do | ||
xml['rs'].ln(rel: "up", href: capability_list_url) | ||
xml['rs'].md(capability: "description") | ||
xml.url do | ||
xml.loc capability_list_url | ||
xml['rs'].md(capability: 'capabilitylist') | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
RSpec.describe Sufia::ResourceSyncController do | ||
before do | ||
Rails.cache.clear | ||
end | ||
|
||
describe "source_description" do | ||
let(:writer) { double } | ||
let(:document) { '<xml>' } | ||
let(:capability_list) { Sufia::Engine.routes.url_helpers.capability_list_url(host: 'test.host') } | ||
|
||
it "is successful" do | ||
allow(Sufia::ResourceSync::SourceDescriptionWriter).to receive(:new).with(capability_list_url: capability_list).and_return(writer) | ||
expect(writer).to receive(:write).and_return(document) | ||
get :source_description | ||
expect(response.content_type).to eq 'application/xml' | ||
expect(response.body).to eq document | ||
end | ||
end | ||
|
||
describe "capability_list" do | ||
let(:writer) { double } | ||
let(:document) { '<xml>' } | ||
let(:capability_list) { Sufia::Engine.routes.url_helpers.capability_list_url(host: 'test.host') } | ||
|
||
it "is successful" do | ||
allow(Sufia::ResourceSync::CapabilityListWriter).to receive(:new).with(resource_list_url: "http://test.host/resourcelist", | ||
description_url: "http://test.host/.well-known/resourcesync").and_return(writer) | ||
expect(writer).to receive(:write).and_return(document) | ||
get :capability_list | ||
expect(response.content_type).to eq 'application/xml' | ||
expect(response.body).to eq document | ||
end | ||
end | ||
|
||
describe "resource_list" do | ||
before do | ||
Rails.cache.clear | ||
end | ||
|
||
let(:writer) { double } | ||
let(:document) { '<xml>' } | ||
let(:capability_list) { Sufia::Engine.routes.url_helpers.capability_list_url(host: 'test.host') } | ||
|
||
it "is successful" do | ||
allow(Sufia::ResourceSync::ResourceListWriter).to receive(:new).with(capability_list_url: capability_list, resource_host: "test.host").and_return(writer) | ||
expect(writer).to receive(:write).and_return(document) | ||
get :resource_list | ||
expect(response.content_type).to eq 'application/xml' | ||
expect(response.body).to eq document | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
require 'spec_helper' | ||
|
||
RSpec.describe Sufia::ResourceSync::CapabilityListWriter do | ||
let(:sitemap) { 'http://www.sitemaps.org/schemas/sitemap/0.9' } | ||
let(:rs) { 'http://www.openarchives.org/rs/terms/' } | ||
|
||
let(:resource_list) { 'http://example.com/resourcelist.xml' } | ||
let(:description) { 'http://example.com/resourcesync_description.xml' } | ||
|
||
subject { described_class.new(resource_list_url: resource_list, | ||
description_url: description).write } | ||
let(:xml) { Nokogiri::XML.parse(subject) } | ||
|
||
it "has url to the capability list" do | ||
description_href = xml.xpath('/x:urlset/rs:ln[@rel="up"]/@href', 'x' => sitemap, 'rs' => rs).map(&:value) | ||
expect(description_href).to eq [description] | ||
|
||
capability = xml.xpath('/x:urlset/rs:md/@capability', 'x' => sitemap, 'rs' => rs).map(&:value) | ||
expect(capability).to eq ["capabilitylist"] | ||
|
||
url = xml.xpath('//x:url[1]/x:loc', 'x' => sitemap).text | ||
expect(url).to eq resource_list | ||
capability = xml.xpath('//x:url[1]/rs:md/@capability', 'x' => sitemap, 'rs' => rs).map(&:value) | ||
expect(capability).to eq ["resourcelist"] | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
require 'spec_helper' | ||
|
||
RSpec.describe Sufia::ResourceSync::ResourceListWriter do | ||
let(:sitemap) { 'http://www.sitemaps.org/schemas/sitemap/0.9' } | ||
let!(:private_collection) { create(:private_collection) } | ||
let!(:public_collection) { create(:public_collection) } | ||
let!(:public_work) { create(:public_generic_work) } | ||
let!(:private_work) { create(:work) } | ||
let!(:file_set) { create(:file_set, :public) } | ||
let(:capability_list) { 'http://example.com/capabilityList.xml' } | ||
|
||
subject { described_class.new(resource_host: 'example.com', capability_list_url: capability_list).write } | ||
let(:xml) { Nokogiri::XML.parse(subject) } | ||
|
||
it "has two urls" do | ||
first_url = xml.xpath('//x:url[1]/x:loc', 'x' => sitemap).text | ||
second_url = xml.xpath('//x:url[2]/x:loc', 'x' => sitemap).text | ||
third_url = xml.xpath('//x:url[3]/x:loc', 'x' => sitemap).text | ||
expect(first_url).to eq "http://example.com/collections/#{public_collection.id}" | ||
expect(second_url).to eq "http://example.com/concern/generic_works/#{public_work.id}" | ||
expect(third_url).to eq "http://example.com/concern/file_sets/#{file_set.id}" | ||
expect(xml.xpath('//x:url', 'x' => sitemap).count).to eq 3 | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
require 'spec_helper' | ||
|
||
RSpec.describe Sufia::ResourceSync::SourceDescriptionWriter do | ||
let(:sitemap) { 'http://www.sitemaps.org/schemas/sitemap/0.9' } | ||
let(:rs) { 'http://www.openarchives.org/rs/terms/' } | ||
|
||
let(:capability_list) { 'http://example.com/capabilityList.xml' } | ||
|
||
subject { described_class.new(capability_list_url: capability_list).write } | ||
let(:xml) { Nokogiri::XML.parse(subject) } | ||
|
||
it "has url to the capability list" do | ||
capability = xml.xpath('/x:urlset/rs:md/@capability', 'x' => sitemap, 'rs' => rs).map(&:value) | ||
expect(capability).to eq ["description"] | ||
|
||
url = xml.xpath('//x:url[1]/x:loc', 'x' => sitemap).text | ||
expect(url).to eq capability_list | ||
capability = xml.xpath('//x:url[1]/rs:md/@capability', 'x' => sitemap, 'rs' => rs).map(&:value) | ||
expect(capability).to eq ["capabilitylist"] | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters