module Ldp
module Response
require 'ldp/response/paging'
##
# Wrap the raw Faraday respone with our LDP extensions
def self.wrap client, raw_resp
raw_resp.send(:extend, Ldp::Response)
raw_resp.send(:extend, Ldp::Response::Paging) if raw_resp.has_page?
raw_resp
end
##
# Extract the Link: headers from the HTTP resource
def self.links response
h = {}
Array(response.headers["Link"]).map { |x| x.split(", ") }.flatten.inject(h) do |memo, header|
m = header.match(/<(?.*)>;\s?rel="(?[^"]+)"/)
if m
memo[m[:rel]] ||= []
memo[m[:rel]] << m[:link]
end
memo
end
end
def self.applied_preferences headers
h = {}
Array(headers).map { |x| x.split(",") }.flatten.inject(h) do |memo, header|
m = header.match(/(?[^=;]*)(=(?[^;,]*))?(;\s*(?[^,]*))?/)
includes = (m[:params].match(/include="(?[^"]+)"/)[:include] || "").split(" ")
omits = (m[:params].match(/omit="(?[^"]+)"/)[:omit] || "").split(" ")
memo[m[:key]] = { value: m[:value], includes: includes, omits: omits }
end
end
##
# Is the response an LDP resource?
def self.resource? response
Array(links(response)["type"]).include? Ldp.resource.to_s
end
##
# Is the response an LDP container?
def self.container? response
[
Ldp.basic_container,
Ldp.direct_container,
Ldp.indirect_container
].any? { |x| Array(links(response)["type"]).include? x.to_s }
end
##
# Is the response an LDP RDFSource?
# ldp:Container is a subclass of ldp:RDFSource
def self.rdf_source? response
container?(response) || Array(links(response)["type"]).include?(Ldp.rdf_source)
end
def dup
super.tap do |new_resp|
new_resp.send(:extend, Ldp::Response)
if ::RUBY_VERSION < '2.0'
new_resp.send(:remove_instance_variable, :@graph)
else
new_resp.remove_instance_variable(:@graph)
end
end
end
##
# Link: headers from the HTTP response
def links
@links ||= Ldp::Response.links(self)
end
##
# Is the response an LDP resource?
def resource?
Ldp::Response.resource?(self)
end
##
# Is the response an LDP rdf source?
def rdf_source?
Ldp::Response.rdf_source?(self)
end
##
# Is the response an LDP container
def container?
Ldp::Response.container?(self)
end
def preferences
Ldp::Resource.applied_preferences(headers["Preference-Applied"])
end
##
# Get the subject for the response
def subject
page_subject
end
##
# Get the URI to the response
def page_subject
@page_subject ||= RDF::URI.new env[:url]
end
##
# Is the response paginated?
def has_page?
rdf_source? && graph.has_statement?(RDF::Statement.new(page_subject, RDF.type, Ldp.page))
end
##
# Get the graph for the resource (or a blank graph if there is no metadata for the resource)
def graph
@graph ||= begin
raise UnexpectedContentType, "The resource at #{page_subject} is not an RDFSource" unless rdf_source?
graph = RDF::Graph.new
if resource?
RDF::Reader.for(:ttl).new(StringIO.new(body), :base_uri => page_subject) do |reader|
reader.each_statement do |s|
graph << s
end
end
end
graph
end
end
##
# Extract the ETag for the resource
def etag
@etag ||= headers['ETag']
end
def etag=(val)
@etag = val
end
##
# Extract the last modified header for the resource
def last_modified
@last_modified ||= headers['Last-Modified']
end
def last_modified=(val)
@last_modified = val
end
##
# Extract the Link: rel="type" headers for the resource
def types
Array(links["type"])
end
def includes? preference
key = Ldp.send("prefer_#{preference}") if Ldp.respond_to("prefer_#{preference}")
key ||= preference
preferences["return"][:includes].include?(key) || !preferences["return"][:omits].include?(key)
end
def minimal?
preferences["return"][:value] == "minimal"
end
end
end