Created
December 2, 2021 11:35
-
-
Save abrisse/8f9893549f00e94c25cbe0bea93e532d to your computer and use it in GitHub Desktop.
Ruby RDF SPARQL Generator
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
require 'sparql' | |
module RDF | |
class Literal | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_fragment(_options = {}) | |
to_base | |
end | |
end | |
end | |
module RDF | |
class URI | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_fragment(_options = {}) | |
to_base | |
end | |
end | |
end | |
module RDF | |
class Query | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_fragment(options = {}) | |
q = sparql_internal_fragment(options) | |
if options.delete(:dump_where) | |
"WHERE {\n #{q} \n}" | |
else | |
q | |
end | |
end | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
str = @patterns.map { |e| e.sparql_fragment(options) }.join("\n") | |
if graph_name | |
"GRAPH #{graph_name.sparql_fragment(options)} {\n#{str}\n}\n" | |
else | |
str | |
end | |
end | |
class Pattern | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_fragment(_options = {}) | |
to_s | |
end | |
end | |
class Variable | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_fragment(_options = {}) | |
to_s | |
end | |
end | |
end | |
end | |
module SPARQL | |
module Algebra | |
module Query | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_fragment(options = {}) | |
if options.delete(:dump_where) | |
"WHERE {\n #{super} \n}" | |
else | |
super | |
end | |
end | |
end | |
end | |
end | |
module SPARQL | |
module Algebra | |
class Operator | |
def sparql_fragment(options = {}) | |
sparql_internal_fragment(options) | |
end | |
class Construct | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"CONSTRUCT {\n" + selection_sparql(operands[0], options) + "\n}\n#{operands[1].sparql_fragment(options.merge(dump_where: true))}" | |
end | |
private | |
def selection_sparql(array, options = {}) | |
array.map { |e| e.sparql_fragment(options) }.join("\n") | |
end | |
end | |
class Project | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
distinct = options.delete(:distinct) | |
"SELECT#{distinct ? ' DISTINCT' : ''} #{operands[0].map { |e| e.sparql_fragment(options) }.join(' ')}\n#{operands[1].sparql_fragment(options.merge(dump_where: true))}" | |
end | |
end | |
class Dataset | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_fragment(options = {}) | |
operands[0].each_with_object('') do |graph, str| | |
str << if graph.is_a?(Array) | |
"FROM #{graph[0].upcase} #{graph[1].sparql_fragment(options)}\n" | |
else | |
"FROM #{graph.sparql_fragment(options)}\n" | |
end | |
end.tap do |str| | |
str << operands[1].sparql_fragment(options) | |
end | |
end | |
end | |
class Distinct | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
operands[0].sparql_fragment(options.merge(distinct: true)) | |
end | |
end | |
class Prefix | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
str = '' | |
str << prefixes_sparql(operands[0]) + "\n" unless options[:no_prefixes] | |
str << operands[1].sparql_fragment(options) | |
end | |
private | |
def prefixes_sparql(array) | |
array.map { |e| "PREFIX #{e[0]} #{e[1].to_base}" }.join("\n") | |
end | |
end | |
class LeftJoin | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
str = '' | |
str << operands[0].sparql_fragment(options) + "\nOPTIONAL { \n" + operands[1].sparql_fragment(options) + "\n" | |
str << 'FILTER (' + operands[2].sparql_fragment(options) + ") \n" if operands[2] | |
str << '}' | |
end | |
end | |
class Join | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
operands.map { |operand| wrap_operand(operand, options) }.join("\n") | |
end | |
# Wrap operand | |
# | |
# Necessary for sub-queries | |
# @param [Operand] the Algebra operator | |
# @param [Hash{Symbol => Object}] options ({}) | |
# @return [String] | |
def wrap_operand(operand, options) | |
case operand | |
when SPARQL::Algebra::Operator::Slice, SPARQL::Algebra::Operator::Project, SPARQL::Algebra::Operator::Distinct | |
"{\n#{operand.sparql_fragment(options)}\n}" | |
# when RDF::Query, SPARQL::Algebra::Operator::Join, SPARQL::Algebra::Operator::Path | |
# operand.sparql_fragment(options) | |
else | |
operand.sparql_fragment(options) | |
end | |
end | |
end | |
class Union | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"{\n" + operands[0].sparql_fragment(options) + "\n} UNION {\n" + operands[1].sparql_fragment(options) + "\n}" | |
end | |
end | |
class Filter | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"#{operands[1].sparql_fragment(options)} \nFILTER (#{operands[0].sparql_fragment(options)}) ." | |
end | |
end | |
# -------------------------- | |
# Evaluatable | |
# -------------------------- | |
class Exprlist | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
'(' + operands.map { |o| o.sparql_fragment(options) }.join(') && (') + ')' | |
end | |
end | |
class Regex | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"regex(#{operands[0].sparql_fragment(options)}, #{operands[1].sparql_fragment(options)})" | |
end | |
end | |
class StrStarts | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"strstarts(#{operands[0].sparql_fragment(options)}, #{operands[1].sparql_fragment(options)})" | |
end | |
end | |
class Str | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"str(#{operands[0].sparql_fragment(options)})" | |
end | |
end | |
class Not | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"!#{operands[0].sparql_fragment(options)}" | |
end | |
end | |
class Contains | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"contains(#{operands[0].sparql_fragment(options)}, #{operands[1].sparql_fragment(options)})" | |
end | |
end | |
class Bound | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"bound(#{operands[0].sparql_fragment(options)})" | |
end | |
end | |
class IsBlank | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"isBlank(#{operands[0].sparql_fragment(options)})" | |
end | |
end | |
class NotExists | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"NOT EXISTS {\n#{operands[0].sparql_fragment(options)}\n}" | |
end | |
end | |
class Compare | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"#{operands[0].sparql_fragment(options)} #{self.class.const_get(:NAME)} #{operands[1].sparql_fragment(options)}" | |
end | |
end | |
class IsLiteral | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"isLiteral(#{operands[0].sparql_fragment(options)})" | |
end | |
end | |
class Multiply | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"#{operands[0].sparql_fragment(options)} * #{operands[1].sparql_fragment(options)}" | |
end | |
end | |
class Divide | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"#{operands[0].sparql_fragment(options)} / #{operands[1].sparql_fragment(options)}" | |
end | |
end | |
class Plus | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"#{operands[0].sparql_fragment(options)} + #{operands[1].sparql_fragment(options)}" | |
end | |
end | |
class Subtract | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"#{operands[0].sparql_fragment(options)} - #{operands[1].sparql_fragment(options)}" | |
end | |
end | |
class Or | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"#{operands[0].sparql_fragment(options)} || #{operands[1].sparql_fragment(options)}" | |
end | |
end | |
class And | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"#{operands[0].sparql_fragment(options)} && #{operands[1].sparql_fragment(options)}" | |
end | |
end | |
class In | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"#{operands[0].sparql_fragment(options)} IN (#{operands[1..-1].map{|e| e.sparql_fragment(options)}.join(', ')})" | |
end | |
end | |
class NotIn | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"#{operands[0].sparql_fragment(options)} NOT IN (#{operands[1..-1].map{|e| e.sparql_fragment(options)}.join(', ')})" | |
end | |
end | |
class Extend | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
operands[1].sparql_fragment(options).tap do |full_str| | |
operands[0].each_with_object(full_str) do |operation, str| | |
as, expression = operation | |
str << "\nBIND (#{expression.sparql_fragment(options)} AS #{as.sparql_fragment(options)}) ." | |
end | |
end | |
end | |
end | |
class Path | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"#{operands[0].sparql_fragment(options)} #{operands[1].sparql_fragment(options)} #{operands[2].sparql_fragment(options)} ." | |
end | |
end | |
class Seq | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"#{operands[0].sparql_fragment(options)}/#{operands[1].sparql_fragment(options)}" | |
end | |
end | |
class Reverse | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"^#{operands[0].sparql_fragment(options)}" | |
end | |
end | |
class Alt | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"#{operands[0].sparql_fragment(options)}|#{operands[1].sparql_fragment(options)}" | |
end | |
end | |
class PathPlus | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"#{operands[0].sparql_fragment(options)}+" | |
end | |
end | |
class PathStar | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"#{operands[0].sparql_fragment(options)}*" | |
end | |
end | |
class PathOpt | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"#{operands[0].sparql_fragment(options)}?" | |
end | |
end | |
class Lang | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"lang(#{operands[0].sparql_fragment(options)})" | |
end | |
end | |
class LangMatches | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
"langMatches(#{operands[0].sparql_fragment(options)}, #{operands[1].sparql_fragment(options)})" | |
end | |
end | |
class Slice | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_fragment(options = {}) | |
super.tap do |str| | |
str << "\nLIMIT #{operands[1]}" | |
str << " OFFSET #{operands[0]}" unless operands[0] == :_ | |
end | |
end | |
def sparql_internal_fragment(options = {}) | |
operands[2].sparql_fragment(options) | |
end | |
end | |
class Table | |
## | |
# Returns the object SPARQL representation | |
# | |
# @param [Hash{Symbol => Object}] options ({}) | |
# options passed for the generation | |
# @return [String] | |
def sparql_internal_fragment(options = {}) | |
str = "VALUES (#{operands[0][1..-1].map { |e| e.sparql_fragment(options) }.join(' ')}) {\n" | |
operands[1..-1].each do |row| | |
line = '(' | |
row[1..-1].each do |col| | |
line << "#{col[1].sparql_fragment(options)} " | |
end | |
line = line.chop | |
line << ")\n" | |
str << line | |
end | |
str << "}\n" | |
str | |
end | |
end | |
end | |
end | |
end | |
query = %q{ | |
PREFIX uuid: <http://www.perfect-memory.com/profile/showroom/resource/> | |
SELECT ?uri ?uri2 | |
WHERE { | |
VALUES (?uri ?uri2) { | |
(uuid:e5a0607b-8158-430d-b05c-2d064aee01a6 "pop") | |
(uuid:f5cebb49-3a34-4f4b-91de-866623aae777 "rock") | |
} | |
} | |
} | |
puts ::SPARQL::Grammar.parse(query).sparql_fragment |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment