lib/sparql/results.rb in sparql-0.0.2 vs lib/sparql/results.rb in sparql-0.1.0

- old
+ new

@@ -116,26 +116,43 @@ # Serialize solutions using the determined format # # @param [RDF::Query::Solutions, RDF::Queryable, Boolean] solutions # Solutions as either a solution set, a Queryable object (such as a graph) or a Boolean value # @param [Hash{Symbol => Object}] options - # @option options [:format] + # @option options [#to_sym] :format # Format of results, one of :html, :json or :xml. # May also be an RDF::Writer format to serialize DESCRIBE or CONSTRUCT results - # @option options [:content_type] + # @option options [String] :content_type # Format of results, one of 'application/sparql-results+json' or 'application/sparql-results+xml' # May also be an RDF::Writer content_type to serialize DESCRIBE or CONSTRUCT results + # @option options [Array<String>] :content_types + # Similar to :content_type, but takes an ordered array of appropriate content types, + # and serializes using the first appropriate type, including wild-cards. # @return [String] # String with serialized results and #content_type + # @raise [RDF::WriterError] when inappropriate formatting options are used def serialize_results(solutions, options = {}) - format = options[:format] - content_type = options[:content_type] + format = options[:format].to_sym if options[:format] + content_type = options[:content_type].to_s.split(';').first + content_types = options[:content_types] || ['*/*'] format ||= RDF::Query::Solutions::MIME_TYPES.invert[content_type] if content_type + if !format && !content_type + case solutions + when RDF::Queryable + content_type = first_content_type(content_types, RDF::Format.content_types.keys) || 'text/plain' + format = RDF::Writer.for(:content_type => content_type).to_sym + else + content_type = first_content_type(content_types, RDF::Query::Solutions::MIME_TYPES.values) || 'application/sparql-results+xml' + format = RDF::Query::Solutions::MIME_TYPES.invert[content_type] + end + end + serialization = case solutions - when TrueClass, FalseClass - case format ||= :xml + when TrueClass, FalseClass, RDF::Literal::TRUE, RDF::Literal::FALSE + solutions = solutions.object if solutions.is_a?(RDF::Literal) + case format when :json require 'json' unless defined?(::JSON) {:boolean => solutions}.to_json when :xml require 'builder' unless defined?(::Builder) @@ -147,22 +164,33 @@ when :html require 'builder' unless defined?(::Builder) content_type = "text/html" xml = ::Builder::XmlMarkup.new(:indent => 2) xml.div(solutions.to_s, :class => "sparql") + else + raise RDF::WriterError, "Unknown format #{(format || content_type).inspect} for #{solutions.class}" end when RDF::Queryable + begin + require 'linkeddata' + rescue LoadError => e + require 'rdf/ntriples' + end fmt = RDF::Format.for(format ? format.to_sym : {:content_type => content_type}) fmt ||= RDF::NTriples::Format format ||= fmt.to_sym - content_type ||= fmt.content_types.first - fmt.writer.buffer << solutions + content_type ||= fmt.content_type.first + results = solutions.dump(format, options) + raise RDF::WriterError, "Unknown format #{fmt.inspect} for #{solutions.class}" unless results + results when RDF::Query::Solutions - case format ||= :xml + case format when :json then solutions.to_json when :xml then solutions.to_xml when :html then solutions.to_html + else + raise RDF::WriterError, "Unknown format #{(format || content_type).inspect} for #{solutions.class}" end end content_type ||= RDF::Query::Solutions::MIME_TYPES[format] if format @@ -182,9 +210,29 @@ <p>%s: %s</p> </body> </html> ).freeze + ## + # Find a content_type from a list using an ordered list of acceptable content types + # using wildcard matching + # + # @param [Array<String>] acceptable + # @param [Array<String>] available + # @return [String] + # + # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1 + def first_content_type(acceptable, available) + return acceptable.first if available.empty? + available.flatten! + acceptable.each do |pattern| + type = available.detect { |t| File.fnmatch(pattern, t) } + return type if type + end + nil + end + module_function :first_content_type + ## # Serialize error results # # Returns appropriate content based upon an execution exception # @param [Exception] exception