text:
# -*- coding: utf-8 -*-
require_relative 'spec_helper'
require 'webmock/rspec'
require 'json'
require 'rdf/turtle'
require 'rexml/document'

describe SPARQL::Client do
  let(:query) {'DESCRIBE ?kb WHERE { ?kb <http://data.linkedmdb.org/resource/movie/actor_name> "Kevin Bacon" . }'}
  let(:construct_query) {'CONSTRUCT {?kb <http://data.linkedmdb.org/resource/movie/actor_name> "Kevin Bacon" . } WHERE { ?kb <http://data.linkedmdb.org/resource/movie/actor_name> "Kevin Bacon" . }'}
  let(:select_query) {'SELECT ?kb WHERE { ?kb <http://data.linkedmdb.org/resource/movie/actor_name> "Kevin Bacon" . }'}
  let(:describe_query) {'DESCRIBE ?kb WHERE { ?kb <http://data.linkedmdb.org/resource/movie/actor_name> "Kevin Bacon" . }'}
  let(:ask_query) {'ASK WHERE { ?kb <http://data.linkedmdb.org/resource/movie/actor_name> "Kevin Bacon" . }'}
  let(:update_query) {'DELETE {?s ?p ?o} WHERE {}'}

  describe "#initialize" do
    it "calls block" do
      expect {|b| described_class.new('http://data.linkedmdb.org/sparql', &b)}.to yield_control
      described_class.new('http://data.linkedmdb.org/sparql') do |sparql|
        expect(sparql).to be_a(SPARQL::Client)
      end
    end
  end

  context "when querying a remote endpoint" do
    subject {SPARQL::Client.new('http://data.linkedmdb.org/sparql')}

    def response(header)
      response = Net::HTTPSuccess.new '1.1', 200, 'body'
      response.content_type = header if header
      allow(response).to receive(:body).and_return('body')
      response
    end

    describe "#ask" do
      specify do
        expect(subject.ask.where([:s, :p, :o]).to_s).to eq "ASK WHERE { ?s ?p ?o . }"
      end
    end

    describe "#select" do
      specify do
        expect(subject.select.where([:s, :p, :o]).to_s).to eq "SELECT * WHERE { ?s ?p ?o . }"
      end
    end

    describe "#describe" do
      specify do
        expect(subject.describe.where([:s, :p, :o]).to_s).to eq "DESCRIBE * WHERE { ?s ?p ?o . }"
      end
    end

    describe "#construct" do
      specify do
        expect(subject.construct([:s, :p, :o]).where([:s, :p, :o]).to_s).to eq "CONSTRUCT { ?s ?p ?o . } WHERE { ?s ?p ?o . }"
      end
    end

    it "handles successful response with plain header" do
      expect(subject).to receive(:request).and_yield response('text/plain')
      expect(RDF::Reader).to receive(:for).with(content_type: 'text/plain').and_call_original
      subject.query(query)
    end

    it "handles successful response with boolean header" do
      expect(subject).to receive(:request).and_yield response(SPARQL::Client::RESULT_BOOL)
      expect(subject.query(query)).to be_falsey
    end

    it "handles successful response with JSON header" do
      expect(subject).to receive(:request).and_yield response(SPARQL::Client::RESULT_JSON)
      expect(subject.class).to receive(:parse_json_bindings)
      subject.query(query)
    end

    it "handles successful response with XML header" do
      expect(subject).to receive(:request).and_yield response(SPARQL::Client::RESULT_XML)
      expect(subject.class).to receive(:parse_xml_bindings)
      subject.query(query)
    end

    it "handles successful response with CSV header" do
      expect(subject).to receive(:request).and_yield response(SPARQL::Client::RESULT_CSV)
      expect(subject.class).to receive(:parse_csv_bindings)
      subject.query(query)
    end

    it "handles successful response with TSV header" do
      expect(subject).to receive(:request).and_yield response(SPARQL::Client::RESULT_TSV)
      expect(subject.class).to receive(:parse_tsv_bindings)
      subject.query(query)
    end

    it "handles successful response with overridden XML header" do
      expect(subject).to receive(:request).and_yield response(SPARQL::Client::RESULT_XML)
      expect(subject.class).to receive(:parse_json_bindings)
      subject.query(query, content_type: SPARQL::Client::RESULT_JSON)
    end

    it "handles successful response with no content type" do
      expect(subject).to receive(:request).and_yield response(nil)
      expect { subject.query(query) }.not_to raise_error
    end

    it "handles successful response with overridden plain header" do
      expect(subject).to receive(:request).and_yield response('text/plain')
      expect(RDF::Reader).to receive(:for).with(content_type: 'text/turtle').and_call_original
      subject.query(query, content_type: 'text/turtle')
    end

    it "handles successful response with custom headers" do
      expect(subject).to receive(:request).with(anything, {"Authorization" => "Basic XXX=="}).
        and_yield response('text/plain')
      subject.query(query, headers: {"Authorization" => "Basic XXX=="})
    end

    it "handles successful response with initial custom headers" do
      options = {headers: {"Authorization" => "Basic XXX=="}, method: :get}
      client = SPARQL::Client.new('http://data.linkedmdb.org/sparql', **options)
      client.instance_variable_set :@http, double(request: response('text/plain'))
      expect(Net::HTTP::Get).to receive(:new).with(anything, hash_including(options[:headers]))
      client.query(query)
    end

    it "enables overriding the http method" do
      stub_request(:get, "http://data.linkedmdb.org/sparql?query=DESCRIBE%20?kb%20WHERE%20%7B%20?kb%20%3Chttp://data.linkedmdb.org/resource/movie/actor_name%3E%20%22Kevin%20Bacon%22%20.%20%7D").
         to_return(status: 200, body: "", headers: { 'Content-Type' => 'application/n-triples'})
      allow(subject).to receive(:request_method).with(query).and_return(:get)
      expect(subject).to receive(:make_get_request).and_call_original
      subject.query(query)
    end

    it "supports international characters in response body" do
      client = SPARQL::Client.new('http://dbpedia.org/sparql')
      json = {
        results: {
          bindings: [
            name: {type: :literal, "xml:lang" => "jp", value: "東京"}
          ],
        }
      }.to_json
      WebMock.stub_request(:any, 'http://dbpedia.org/sparql').
        to_return(body: json, status: 200, headers: { 'Content-Type' => SPARQL::Client::RESULT_JSON})
      query = "SELECT ?name WHERE { <http://dbpedia.org/resource/Tokyo> <http://dbpedia.org/property/nativeName> ?name }"
      result = client.query(query, content_type: SPARQL::Client::RESULT_JSON).first
      expect(result[:name].to_s).to eq "東京"
    end

    it "handles successful response with default graph specified" do
      WebMock.stub_request(:post, 'https://dbpedia.org/sparql?default-graph-uri=https://example.org/').
        to_return(body: '{}', status: 200, headers: { 'Content-Type' => 'application/sparql-results+json'})
      client = SPARQL::Client.new('https://dbpedia.org/sparql', graph: "https://example.org/")
      client.query(query)
      expect(WebMock).to have_requested(:post, "https://dbpedia.org/sparql?default-graph-uri=https://example.org/")
    end

    it "generates IOError when querying closed client" do
      subject.close
      expect{ subject.query(ask_query) }.to raise_error IOError
    end

    context "Redirects" do
      before do
        WebMock.stub_request(:any, 'http://data.linkedmdb.org/sparql').
          to_return(body: '{}', status: 303, headers: { 'Location' => 'http://sparql.linkedmdb.org/sparql' })
      end

      it 'follows redirects' do
        WebMock.stub_request(:any, 'http://sparql.linkedmdb.org/sparql').
          to_return(body: '{}', status: 200, headers: { content_type: SPARQL::Client::RESULT_JSON})
        subject.query(ask_query)
        expect(WebMock).to have_requested(:post, "http://sparql.linkedmdb.org/sparql").
          with(body: 'query=ASK+WHERE+%7B+%3Fkb+%3Chttp%3A%2F%2Fdata.linkedmdb.org%2Fresource%2Fmovie%2Factor_name%3E+%22Kevin+Bacon%22+.+%7D')
      end

      it 'raises an error on infinate redirects' do
        WebMock.stub_request(:any, 'http://sparql.linkedmdb.org/sparql').
          to_return(body: '{}', status: 303, headers: { 'Location' => 'http://sparql.linkedmdb.org/sparql' })
        expect{ subject.query(ask_query) }.to raise_error SPARQL::Client::ServerError
      end
    end

    context "Accept Header" do
      it "uses application/sparql-results+json for ASK" do
        WebMock.stub_request(:any, 'http://data.linkedmdb.org/sparql').
          to_return(body: '{}', status: 200, headers: { 'Content-Type' => 'application/sparql-results+json'})
        subject.query(ask_query)
        expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/sparql").
          with(headers: {'Accept'=>'application/sparql-results+json, application/sparql-results+xml, text/boolean, text/tab-separated-values;q=0.8, text/csv;q=0.2, */*;q=0.1'})
      end

      it "uses application/n-triples for CONSTRUCT" do
        WebMock.stub_request(:any, 'http://data.linkedmdb.org/sparql').
          to_return(body: '', status: 200, headers: { 'Content-Type' => 'application/n-triples'})
        subject.query(construct_query)
        expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/sparql").
          with(headers: {'Accept'=>'application/n-triples, text/plain, */*;q=0.1'})
      end

      it "uses application/n-triples for DESCRIBE" do
        WebMock.stub_request(:any, 'http://data.linkedmdb.org/sparql').
          to_return(body: '', status: 200, headers: { 'Content-Type' => 'application/n-triples'})
        subject.query(describe_query)
        expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/sparql").
          with(headers: {'Accept'=>'application/n-triples, text/plain, */*;q=0.1'})
      end

      it "uses application/sparql-results+json for SELECT" do
        WebMock.stub_request(:any, 'http://data.linkedmdb.org/sparql').
          to_return(body: '{}', status: 200, headers: { 'Content-Type' => 'application/sparql-results+json'})
        subject.query(select_query)
        expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/sparql").
          with(headers: {'Accept'=>'application/sparql-results+json, application/sparql-results+xml, text/boolean, text/tab-separated-values;q=0.8, text/csv;q=0.2, */*;q=0.1'})
      end
    end

    context 'User-Agent header' do
      it "uses default if not specified" do
        WebMock.stub_request(:any, 'http://data.linkedmdb.org/sparql').
          to_return(body: '{}', status: 200, headers: { 'Content-Type' => 'application/sparql-results+json'})
        subject.query(select_query)
        expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/sparql").
          with(headers: {'User-Agent' => "Ruby SPARQL::Client/#{SPARQL::Client::VERSION}"})
      end

      it "uses user-provided value in query" do
        WebMock.stub_request(:any, 'http://data.linkedmdb.org/sparql').
          to_return(body: '{}', status: 200, headers: { 'Content-Type' => 'application/sparql-results+json'})
        subject.query(select_query, headers: {'User-Agent' => 'Foo'})
        expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/sparql").
          with(headers: {'User-Agent' => "Foo"})
      end

      it "uses user-provided value in initialization" do
        client = SPARQL::Client.new('http://data.linkedmdb.org/sparql', headers: {'User-Agent' => 'Foo'})
        WebMock.stub_request(:any, 'http://data.linkedmdb.org/sparql').
          to_return(body: '{}', status: 200, headers: { 'Content-Type' => 'application/sparql-results+json'})
        client.query(select_query)
        expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/sparql").
          with(headers: {'User-Agent' => "Foo"})
      end
    end

    context "Alternative Endpoint" do
      it "uses the default endpoint if no alternative endpoint is provided" do
        WebMock.stub_request(:any, 'http://data.linkedmdb.org/sparql').
          to_return(body: '', status: 200)
        subject.update(update_query)
        expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/sparql")
      end

      it "uses the alternative endpoint if provided" do
        WebMock.stub_request(:any, 'http://data.linkedmdb.org/alternative').
          to_return(body: '', status: 200)
        subject.update(update_query, endpoint: "http://data.linkedmdb.org/alternative")
        expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/alternative")
      end

      it "does not use the alternative endpoint for a select query" do
        WebMock.stub_request(:any, 'http://data.linkedmdb.org/sparql').
          to_return(body: '', status: 200)
        WebMock.stub_request(:any, 'http://data.linkedmdb.org/alternative').
          to_return(body: '', status: 200)
        subject.update(update_query, endpoint: "http://data.linkedmdb.org/alternative")
        expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/alternative")
        subject.query(select_query)
        expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/sparql")
      end
    end

    context "with multiple Graphs" do
      let(:get_graph_client){ SPARQL::Client.new('http://data.linkedmdb.org/sparql', method: 'get', graph: 'http://data.linkedmdb.org/graph1') }
      let(:post_graph_client10){ SPARQL::Client.new('http://data.linkedmdb.org/sparql', method: 'post', graph: 'http://data.linkedmdb.org/graph1', protocol: '1.0') }
      let(:post_graph_client11){ SPARQL::Client.new('http://data.linkedmdb.org/sparql', method: 'post', graph: 'http://data.linkedmdb.org/graph1', protocol: '1.1') }

      it "should create 'query via GET' requests" do
        WebMock.stub_request(:get, 'http://data.linkedmdb.org/sparql?default-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1&query=SELECT%20%3Fkb%20WHERE%20%7B%20%3Fkb%20%3Chttp%3A%2F%2Fdata.linkedmdb.org%2Fresource%2Fmovie%2Factor_name%3E%20%22Kevin%20Bacon%22%20.%20%7D').
          to_return(body: '{}', status: 200, headers: { 'Content-Type' => 'application/sparql-results+json'})
        get_graph_client.query(select_query)
        expect(WebMock).to have_requested(:get, "http://data.linkedmdb.org/sparql?default-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1&query=SELECT%20%3Fkb%20WHERE%20%7B%20%3Fkb%20%3Chttp%3A%2F%2Fdata.linkedmdb.org%2Fresource%2Fmovie%2Factor_name%3E%20%22Kevin%20Bacon%22%20.%20%7D")
      end

      it "should create 'query via URL-encoded Post' requests" do
        WebMock.stub_request(:post, 'http://data.linkedmdb.org/sparql?default-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1').
          to_return(body: '{}', status: 200, headers: { 'Content-Type' => 'application/sparql-results+json'})
        post_graph_client10.query(select_query)
        expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/sparql?default-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1").
          with(body: "query=SELECT+%3Fkb+WHERE+%7B+%3Fkb+%3Chttp%3A%2F%2Fdata.linkedmdb.org%2Fresource%2Fmovie%2Factor_name%3E+%22Kevin+Bacon%22+.+%7D&default-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1")
      end

      it "should create 'query via Post directly' requests" do
        WebMock.stub_request(:post, 'http://data.linkedmdb.org/sparql?default-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1').
          to_return(body: '{}', status: 200, headers: { 'Content-Type' => 'application/sparql-results+json'})
        post_graph_client11.query(select_query)
        expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/sparql?default-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1").
          with(body: select_query)
      end

      it "should create requests for 'update via URL-encoded POST'" do
        WebMock.stub_request(:post, 'http://data.linkedmdb.org/sparql?using-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1').
          to_return(body: '{}', status: 200)
        post_graph_client10.update(update_query)
        expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/sparql?using-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1").
          with(body: "update=DELETE+%7B%3Fs+%3Fp+%3Fo%7D+WHERE+%7B%7D&using-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1")
      end

      it "should create requests for 'update via POST directly'" do
        WebMock.stub_request(:post, 'http://data.linkedmdb.org/sparql?using-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1').
          to_return(body: '{}', status: 200)
        post_graph_client11.update(update_query)
        expect(WebMock).to have_requested(:post, "http://data.linkedmdb.org/sparql?using-graph-uri=http%3A%2F%2Fdata.linkedmdb.org%2Fgraph1").
          with(body: update_query)
      end
    end

    context "Error response" do
      {
        "bad request" => {status: 400, error: SPARQL::Client::MalformedQuery },
        "unauthorized" => {status: 401, error: SPARQL::Client::ClientError },
        "not found" => {status: 404, error: SPARQL::Client::ClientError },
        "internal server error" => {status: 500, error: SPARQL::Client::ServerError },
        "not implemented" => {status: 501, error: SPARQL::Client::ServerError },
        "service unavailable" => {status: 503, error: SPARQL::Client::ServerError },
      }.each do |test, params|
        it "detects #{test}" do
          WebMock.stub_request(:any, 'http://data.linkedmdb.org/sparql').
            to_return(body: 'the body', status: params[:status], headers: {'Content-Type' => 'text/plain'})
          expect {
            subject.query(select_query)
          }.to raise_error(params[:error], "the body Processing query #{select_query}")
        end
      end
    end
  end

  context "when querying an RDF::Repository" do
    before(:all) {require 'sparql'}
    let(:repo) {RDF::Repository.new}
    let(:graph) {RDF::Graph.new << RDF::Statement(RDF::URI('http://example/s'), RDF::URI('http://example/p'), "o")}
    subject {SPARQL::Client.new(repo)}

    it "queries repository" do
      expect(SPARQL).to receive(:execute).with(query, repo, any_args)
      subject.query(query)
    end

    describe "#insert_data" do
      specify do
        subject.insert_data(graph)
        expect(repo.count).to eq 1
      end
    end

    describe "#delete_data" do
      specify do
        subject.delete_data(graph)
        expect(repo.count).to eq 0
      end
    end

    describe "#delete_insert" do
      specify do
        expect {subject.delete_insert(graph, graph)}.not_to raise_error
      end
    end

    describe "#clear_graph" do
      specify do
        expect {subject.clear_graph('http://example/')}.to raise_error(IOError)
      end
    end

    describe "#clear" do
      specify do
        subject.clear(:all)
        expect(repo.count).to eq 0
      end
    end

    describe "#query" do
      it "raises error on malformed query" do
        expect do
          expect {subject.query("Invalid SPARQL")}.to raise_error(SPARQL::MalformedQuery)
        end.to write("ERROR").to(:error)
      end
    end
  end

  context "when parsing XML" do
    %i(nokogiri rexml).each do |library|
      context "using #{library}" do
        it "parses binding results correctly" do
          xml = File.read("spec/fixtures/results.xml")
          nodes = {}
          solutions = SPARQL::Client::parse_xml_bindings(xml, nodes, library: library)
          expected = RDF::Query::Solutions.new([
            RDF::Query::Solution.new(
              x: RDF::Node.new("r2"),
              hpage: RDF::URI.new("http://work.example.org/bob/"),
              name: RDF::Literal.new("Bob", language: "en"),
              age: RDF::Literal.new("30", datatype: "http://www.w3.org/2001/XMLSchema#integer"),
              mbox: RDF::URI.new("mailto:bob@work.example.org"),
              triple: RDF::Statement(
                RDF::URI('http://work.example.org/s'),
                RDF::URI('http://work.example.org/p'),
                RDF::URI('http://work.example.org/o')),
            )
          ])
          expect(solutions.variable_names).to eq expected.variable_names
          expect(solutions).to eq expected
          expect(solutions[0]["x"]).to eq nodes["r2"]
          expect(solutions.variable_names).to eq %i(x hpage name age mbox triple)
        end

        it "parses results missing variables" do
          xml = File.read("spec/fixtures/results2.xml")
          nodes = {}
          solutions = SPARQL::Client::parse_xml_bindings(xml, nodes, library: library)
          expected = RDF::Query::Solutions.new([
            RDF::Query::Solution.new(v: RDF::Literal(1))
          ])
          expected.variable_names = %i(v w)
          expect(solutions.variable_names).to eq %i(v w)
          expect(solutions).to eq expected
        end

        it "parses boolean true results correctly" do
          xml = File.read("spec/fixtures/bool_true.xml")
          expect(SPARQL::Client::parse_xml_bindings(xml, library: library)).to eq true
        end

        it "parses boolean false results correctly" do
          xml = File.read("spec/fixtures/bool_false.xml")
          expect(SPARQL::Client::parse_xml_bindings(xml, library: library)).to eq false
        end
      end
    end
  end

  context "when parsing JSON" do
    it "parses binding results correctly" do
      json = File.read("spec/fixtures/results.json")
      nodes = {}
      solutions = SPARQL::Client::parse_json_bindings(json, nodes)
      expect(solutions).to eq RDF::Query::Solutions.new([
        RDF::Query::Solution.new(
          x: RDF::Node.new("r2"),
          hpage: RDF::URI.new("http://work.example.org/bob/"),
          name: RDF::Literal.new("Bob", language: "en"),
          age: RDF::Literal.new("30", datatype: "http://www.w3.org/2001/XMLSchema#integer"),
          mbox: RDF::URI.new("mailto:bob@work.example.org"),
          triple: RDF::Statement(
            RDF::URI('http://work.example.org/s'),
            RDF::URI('http://work.example.org/p'),
            RDF::URI('http://work.example.org/o')),
        )
      ])
      expect(solutions[0]["x"]).to eq nodes["r2"]
      expect(solutions.variable_names).to eq %i(x hpage name age mbox triple)
    end

    it "parses boolean true results correctly" do
      json = '{"boolean": true}'
      expect(SPARQL::Client::parse_json_bindings(json)).to eq true
    end

    it "parses boolean true results correctly" do
      json = '{"boolean": false}'
      expect(SPARQL::Client::parse_json_bindings(json)).to eq false
    end
  end

  context "when parsing CSV" do
    it "parses binding results correctly" do
      csv = File.read("spec/fixtures/results.csv")
      nodes = {}
      solutions = SPARQL::Client::parse_csv_bindings(csv, nodes)
      expect(solutions).to eq RDF::Query::Solutions.new([
        RDF::Query::Solution.new(x: RDF::URI("http://example/x"), literal: RDF::Literal('String')),
        RDF::Query::Solution.new(x: RDF::URI("http://example/x"),
                                 literal: RDF::Literal('String-with-dquote"')),
        RDF::Query::Solution.new(x: RDF::Node.new("b0"), literal: RDF::Literal("Blank node")),
        RDF::Query::Solution.new(x: RDF::Literal(""), literal: RDF::Literal("Missing 'x'")),
        RDF::Query::Solution.new(x: RDF::Literal(""), literal: RDF::Literal("")),
        RDF::Query::Solution.new(x: RDF::URI("http://example/x"), literal: RDF::Literal('')),
        RDF::Query::Solution.new(x: RDF::Node.new("b1"), literal: RDF::Literal("String-with-lang")),
        RDF::Query::Solution.new(x: RDF::Node.new("b2"), literal: RDF::Literal("123")),
      ])
      expect(solutions[2]["x"]).to eq nodes["b0"]
      expect(solutions[6]["x"]).to eq nodes["b1"]
      expect(solutions[7]["x"]).to eq nodes["b2"]
      expect(solutions.variable_names).to eq %i(x literal)
    end
  end

  context "when parsing TSV" do
    it "parses binding results correctly" do
      tsv = File.read("spec/fixtures/results.tsv")
      nodes = {}
      solutions = SPARQL::Client::parse_tsv_bindings(tsv, nodes)
      expect(solutions).to eq RDF::Query::Solutions.new([
        RDF::Query::Solution.new(x: RDF::URI("http://example/x"), literal: RDF::Literal('String')),
        RDF::Query::Solution.new(x: RDF::URI("http://example/x"),
                                 literal: RDF::Literal('String-with-dquote"')),
        RDF::Query::Solution.new(x: RDF::Node.new("b0"), literal: RDF::Literal("Blank node")),
        RDF::Query::Solution.new(x: RDF::Literal(""), literal: RDF::Literal("Missing 'x'")),
        RDF::Query::Solution.new(x: RDF::Literal(""), literal: RDF::Literal("")),
        RDF::Query::Solution.new(x: RDF::URI("http://example/x"), literal: RDF::Literal('')),
        RDF::Query::Solution.new(x: RDF::Node.new("b1"), literal: RDF::Literal("String-with-lang", language: :en)),
        RDF::Query::Solution.new(x: RDF::Node.new("b2"), literal: RDF::Literal(123)),
        RDF::Query::Solution.new(x: RDF::Node.new("b3"), literal: RDF::Literal::Decimal.new(123.0)),
        RDF::Query::Solution.new(x: RDF::Node.new("b4"), literal: RDF::Literal(123.0e1)),
        RDF::Query::Solution.new(x: RDF::Node.new("b5"), literal: RDF::Literal(0.1e1)),
      ])
      expect(solutions[2]["x"]).to eq nodes["b0"]
      expect(solutions[6]["x"]).to eq nodes["b1"]
      expect(solutions[7]["x"]).to eq nodes["b2"]
      expect(solutions[8]["x"]).to eq nodes["b3"]
      expect(solutions[9]["x"]).to eq nodes["b4"]
      expect(solutions[10]["x"]).to eq nodes["b5"]
      expect(solutions.variable_names).to eq %i(x literal)
    end
  end
end


text:
require_relative 'spec_helper'

describe 'SPARQL::Client::VERSION' do
  it "matches the VERSION file" do
    expect(SPARQL::Client::VERSION.to_s).to eq File.read(File.join(File.dirname(__FILE__), '..', 'VERSION')).chomp
  end
end

repo_name: ruby-rdf/sparql-client

repo_language: Ruby

mime_type: text/plain


text:
require_relative 'spec_helper'

describe SPARQL::Client::Update do
  subject {SPARQL::Client::Update}

  context "when building queries" do
    it "supports INSERT DATA operations" do
      expect(subject).to respond_to(:insert_data)
    end

    it "supports DELETE DATA operations" do
      expect(subject).to respond_to(:delete_data)
    end

    it "supports DELETE/INSERT operations", pending: true do
      expect(subject).to respond_to(:what)
      expect(subject).to respond_to(:delete)
      expect(subject).to respond_to(:insert)
    end

    it "supports LOAD operations" do
      expect(subject).to respond_to(:load)
    end

    it "supports CLEAR operations" do
      expect(subject).to respond_to(:clear)
    end

    it "supports CREATE operations" do
      expect(subject).to respond_to(:create)
    end

    it "supports DROP operations" do
      expect(subject).to respond_to(:drop)
    end

    it "supports COPY operations", pending: true do
      expect(subject).to respond_to(:copy) # TODO
    end

    it "supports MOVE operations", pending: true do
      expect(subject).to respond_to(:move) # TODO
    end

    it "supports ADD operations", pending: true do
      expect(subject).to respond_to(:add) # TODO
    end
  end

  context "when building INSERT DATA queries" do
    it "supports empty input" do
      expect(subject.insert_data(RDF::Graph.new).to_s).to eq "INSERT DATA {\n}\n"
    end

    it "expects results not statements" do
      expect(subject.insert_data(RDF::Graph.new)).not_to be_expects_statements
    end

    it "supports non-empty input" do
      data = RDF::Graph.new do |graph|
        graph << [RDF::URI('http://example.org/jhacker'), RDF::URI("http://xmlns.com/foaf/0.1/name"), "J. Random Hacker"]
      end
      expect(subject.insert_data(data).to_s).to eq "INSERT DATA {\n<http://example.org/jhacker> <http://xmlns.com/foaf/0.1/name> \"J. Random Hacker\" .\n}\n"
    end

    it "supports the GRAPH modifier" do
      [subject.insert_data(RDF::Graph.new, graph: 'http://example.org/'),
       subject.insert_data(RDF::Graph.new).graph('http://example.org/')].each do |example|
        expect(example.to_s).to eq "INSERT DATA { GRAPH <http://example.org/> {\n}}\n"
      end
    end
  end

  context "when building DELETE DATA queries" do
    it "supports empty input" do
      expect(subject.delete_data(RDF::Graph.new).to_s).to eq "DELETE DATA {\n}\n"
    end

    it "expects statements not results" do
      expect(subject.delete_data(RDF::Graph.new)).to be_expects_statements
    end

    it "supports non-empty input" do
      data = RDF::Graph.new do |graph|
        graph << [RDF::URI('http://example.org/jhacker'), RDF::URI("http://xmlns.com/foaf/0.1/name"), "J. Random Hacker"]
      end
      expect(subject.delete_data(data).to_s).to eq "DELETE DATA {\n<http://example.org/jhacker> <http://xmlns.com/foaf/0.1/name> \"J. Random Hacker\" .\n}\n"
    end

    it "supports the GRAPH modifier" do
      [subject.delete_data(RDF::Graph.new, graph: 'http://example.org/'),
       subject.delete_data(RDF::Graph.new).graph('http://example.org/')].each do |example|
        expect(example.to_s).to eq "DELETE DATA { GRAPH <http://example.org/> {\n}}\n"
      end
    end
  end

  context "when building INSERT/DELETE queries" do
    it "should do something"
  end

  context "when building LOAD queries" do
    let(:from_url) {'http://example.org/data.rdf'}

    it "requires a source URI" do
      expect(subject.load(from_url).to_s).to eq "LOAD <#{from_url}>"
    end

    it "expects statements not results" do
      expect(subject.load(from_url)).to be_expects_statements
    end

    it "supports the SILENT modifier" do
      [subject.load(from_url).silent,
       subject.load(from_url, silent: true)].each do |example|
        expect(example.to_s).to eq "LOAD SILENT <#{from_url}>"
      end
    end

    it "supports the INTO GRAPH modifier" do
      [subject.load(from_url).into(from_url),
       subject.load(from_url, into: from_url)].each do |example|
        expect(example.to_s).to eq "LOAD <#{from_url}> INTO GRAPH <#{from_url}>"
      end
    end
  end

  context "when building CLEAR queries" do
    it "supports the CLEAR GRAPH operation" do
      graph_uri = 'http://example.org/'
      [subject.clear.graph(graph_uri),
       subject.clear(:graph, graph_uri)].each do |example|
        expect(example.to_s).to eq "CLEAR GRAPH <#{graph_uri}>"
      end
    end

    it "supports the CLEAR DEFAULT operation" do
      [subject.clear.default, subject.clear(:default)].each do |example|
         expect(example.to_s).to eq "CLEAR DEFAULT"
      end
    end

    it "supports the CLEAR NAMED operation" do
      [subject.clear.named, subject.clear(:named)].each do |example|
        expect(example.to_s).to eq "CLEAR NAMED"
      end
    end

    it "supports the CLEAR ALL operation" do
      [subject.clear.all, subject.clear(:all)].each do |example|
        expect(example.to_s).to eq "CLEAR ALL"
      end
    end

    it "expects results not statements" do
      expect(subject.clear.all).not_to be_expects_statements
    end

    it "supports the SILENT modifier" do
      [subject.clear(:all).silent,
       subject.clear(:all, silent: true)].each do |example|
        expect(example.to_s).to eq "CLEAR SILENT ALL"
      end
    end
  end

  context "when building CREATE queries" do
    let(:graph_uri) {'http://example.org/'}

    it "requires a graph URI" do
      expect(subject.create(graph_uri).to_s).to eq "CREATE GRAPH <#{graph_uri}>"
    end

    it "supports the SILENT modifier" do
      [subject.create(graph_uri).silent,
       subject.create(graph_uri, silent: true)].each do |example|
        expect(example.to_s).to eq "CREATE SILENT GRAPH <#{graph_uri}>"
      end
    end

    it "expects statements not results" do
      expect(subject.create(graph_uri)).to be_expects_statements
    end
  end

  context "when building DROP queries" do
    it "supports the DROP GRAPH operation" do
      graph_uri = 'http://example.org/'
      [subject.drop.graph(graph_uri),
       subject.drop(:graph, graph_uri)].each do |example|
        expect(example.to_s).to eq "DROP GRAPH <#{graph_uri}>"
      end
    end

    it "supports the DROP DEFAULT operation" do
      [subject.drop.default, subject.drop(:default)].each do |example|
         expect(example.to_s).to eq "DROP DEFAULT"
      end
    end

    it "supports the DROP NAMED operation" do
      [subject.drop.named, subject.drop(:named)].each do |example|
        expect(example.to_s).to eq "DROP NAMED"
      end
    end

    it "supports the DROP ALL operation" do
      [subject.drop.all, subject.drop(:all)].each do |example|
        expect(example.to_s).to eq "DROP ALL"
      end
    end

    it "expects results not statements" do
      expect(subject.drop.all).not_to be_expects_statements
    end

    it "supports the SILENT modifier" do
      [subject.drop(:all).silent,
       subject.drop(:all, silent: true)].each do |example|
        expect(example.to_s).to eq "DROP SILENT ALL"
      end
    end
  end

  context "when building COPY queries" do
    it "should do something"
  end

  context "when building MOVE queries" do
    it "should do something"
  end

  context "when building ADD queries" do
    it "should do something"
  end
end


text:
require_relative 'spec_helper'
require 'webmock/rspec'
require 'rdf/spec/repository'

describe SPARQL::Client::Repository do
  before :all do
    @base_repo = RDF::Repository.new
  end

  # @see lib/rdf/spec/repository.rb in RDF-spec
  it_behaves_like 'an RDF::Repository' do
    let(:repository) { SPARQL::Client::Repository.new(uri: @base_repo) }
  end

  context "Problematic Tests", skip: true do
    subject {SPARQL::Client::Repository.new(uri: @base_repo)}
    before :each do
      @statements = RDF::Spec.quads

      @base_repo.insert(*@statements)
    end
    its(:count) {is_expected.to eql @statements.size}
  end
end


text:
require_relative 'spec_helper'

describe SPARQL::Client::Query do
  subject {SPARQL::Client::Query}

  context "when building queries" do
    it "supports ASK queries" do
      expect(subject).to respond_to(:ask)
    end

    it "supports SELECT queries" do
      expect(subject).to respond_to(:select)
    end

    it "supports DESCRIBE queries" do
      expect(subject).to respond_to(:describe)
    end

    it "supports CONSTRUCT queries" do
      expect(subject).to respond_to(:construct)
    end
  end

  context "when building ASK queries" do
    context "basic graph patterns" do
      context "where" do
        it "supports simple pattern" do
          expect(subject.ask.where([:s, :p, :o]).to_s).to eq "ASK WHERE { ?s ?p ?o . }"
        end
        it "supports multiple patterns" do
          dbpo =  RDF::URI("http://dbpedia.org/ontology/")
          grs = RDF::URI("http://www.georss.org/georss/")
          patterns = [
            [:city, RDF.type, dbpo + "Place"],
            [:city, RDF::RDFS.label, :name],
            [:city, dbpo + "country", :country],
            [:city, dbpo + "abstract", :abstact],
            [:city, grs + "point", :coords]
          ]
          where = [
            "?city a <http://dbpedia.org/ontology/Place> .",
            "?city <http://www.w3.org/2000/01/rdf-schema#label> ?name .",
            "?city <http://dbpedia.org/ontology/country> ?country .",
            "?city <http://dbpedia.org/ontology/abstract> ?abstact .",
            "?city <http://www.georss.org/georss/point> ?coords ."
          ].join(" ")
          expect(subject.ask.where(*patterns).to_s).to eq "ASK WHERE { #{where} }"
        end
      end

      it "supports whether as an alias for where" do
        expect(subject.ask.whether([:s, :p, :o]).to_s).to eq "ASK WHERE { ?s ?p ?o . }"
      end

      it "expects results not statements" do
        expect(subject.ask.where([:s, :p, :o])).not_to be_expects_statements
      end

      it "supports block with no argument for chaining" do
        expected = "ASK WHERE { ?s ?p ?o . FILTER(regex(?s, 'Abiline, Texas')) }"
        expect(subject.ask.where([:s, :p, :o]) {filter("regex(?s, 'Abiline, Texas')")}.to_s).to eq expected
      end

      it "supports block with argument for chaining" do
        expected = "ASK WHERE { ?s ?p ?o . FILTER(regex(?s, 'Abiline, Texas')) }"
        expect(subject.ask.where([:s, :p, :o]) {|q| q.filter("regex(?s, 'Abiline, Texas')")}.to_s).to eq expected
      end

      context "filter" do
        it "supports filter as a string argument" do
          expected = "ASK WHERE { ?s ?p ?o . FILTER(regex(?s, 'Abiline, Texas')) }"
          expect(subject.ask.where([:s, :p, :o]).filter("regex(?s, 'Abiline, Texas')").to_s).to eq expected
        end
        it "supports multiple string filters" do
          expected = "ASK WHERE { ?s ?p ?o . FILTER(regex(?s, 'Abiline, Texas')) FILTER(langmatches(lang(?o), 'EN')) }"
          expect(subject.ask.where([:s, :p, :o]).
                         filter("regex(?s, 'Abiline, Texas')").
                         filter("langmatches(lang(?o), 'EN')").
                         to_s
                ).to eq expected
        end
      end
    end
  end

  context "when building SELECT queries" do
    it "supports basic graph patterns" do
      expect(subject.select.where([:s, :p, :o]).to_s).to eq "SELECT * WHERE { ?s ?p ?o . }"
    end

    it "supports projection" do
      expect(subject.select(:s).where([:s, :p, :o]).to_s).to eq "SELECT ?s WHERE { ?s ?p ?o . }"
      expect(subject.select(:s, :p).where([:s, :p, :o]).to_s).to eq "SELECT ?s ?p WHERE { ?s ?p ?o . }"
      expect(subject.select(:s, :p, :o).where([:s, :p, :o]).to_s).to eq "SELECT ?s ?p ?o WHERE { ?s ?p ?o . }"
    end

    it "supports FROM" do
      uri = "http://example.org/dft.ttl"
      expect(subject.select.from(RDF::URI.new(uri)).where([:s, :p, :o]).to_s).to eq "SELECT * FROM <#{uri}> WHERE { ?s ?p ?o . }"
    end

    it "supports DISTINCT" do
      expect(subject.select(:s, distinct: true).where([:s, :p, :o]).to_s).to eq "SELECT DISTINCT ?s WHERE { ?s ?p ?o . }"
      expect(subject.select(:s).distinct.where([:s, :p, :o]).to_s).to eq "SELECT DISTINCT ?s WHERE { ?s ?p ?o . }"
      expect(subject.select.distinct.where([:s, :p, :o]).to_s).to eq "SELECT DISTINCT * WHERE { ?s ?p ?o . }"
    end

    it "supports REDUCED" do
      expect(subject.select(:s, reduced: true).where([:s, :p, :o]).to_s).to eq "SELECT REDUCED ?s WHERE { ?s ?p ?o . }"
      expect(subject.select(:s).reduced.where([:s, :p, :o]).to_s).to eq "SELECT REDUCED ?s WHERE { ?s ?p ?o . }"
    end

    it "supports GRAPH" do
      expect(subject.select.graph(:g).where([:s, :p, :o]).to_s).to eq "SELECT * WHERE { GRAPH ?g { ?s ?p ?o . } }"
      expect(subject.select.graph('http://example.org/').where([:s, :p, :o]).to_s).to eq "SELECT * WHERE { GRAPH <http://example.org/> { ?s ?p ?o . } }"
    end

    it "supports COUNT" do
      expect(subject.select(count: { s: :c }).where([:s, :p, :o]).to_s).to eq "SELECT  ( COUNT(?s) AS ?c ) WHERE { ?s ?p ?o . }"
      expect(subject.select(count: { s: :c }, distinct: true).where([:s, :p, :o]).to_s).to eq "SELECT  ( COUNT(DISTINCT ?s) AS ?c ) WHERE { ?s ?p ?o . }"
      expect(subject.select(count: { s: '?c' }).where([:s, :p, :o]).to_s).to eq "SELECT  ( COUNT(?s) AS ?c ) WHERE { ?s ?p ?o . }"
      expect(subject.select(count: { '?s' => '?c' }).where([:s, :p, :o]).to_s).to eq "SELECT  ( COUNT(?s) AS ?c ) WHERE { ?s ?p ?o . }"
      expect(subject.select(:o, count: { s: :c }).where([:s, :p, :o]).to_s).to eq "SELECT ?o ( COUNT(?s) AS ?c ) WHERE { ?s ?p ?o . }"
    end

    it "supports VALUES" do
      expect(subject.select(:s).where([:s, :p, :o]).values(:o, "Object").to_s).to eq 'SELECT ?s WHERE { ?s ?p ?o . VALUES (?o) { ( "Object" ) } }'
      expect(subject.select(:s).where([:s, :p, :o]).values(:o, "1", "2").to_s).to eq 'SELECT ?s WHERE { ?s ?p ?o . VALUES (?o) { ( "1" ) ( "2" ) } }'
      expect(subject.select(:s).where([:s, :p, :o]).values([:o, :p], ["Object", "Predicate"]).to_s).to eq 'SELECT ?s WHERE { ?s ?p ?o . VALUES (?o ?p) { ( "Object" "Predicate" ) } }'
      expect(subject.select(:s).where([:s, :p, :o]).values([:o, :p], ["1", "2"], ["3", "4"]).to_s).to eq 'SELECT ?s WHERE { ?s ?p ?o . VALUES (?o ?p) { ( "1" "2" ) ( "3" "4" ) } }'
      expect(subject.select(:s).where([:s, :p, :o]).values([:o, :p], [nil, "2"], ["3", nil]).to_s).to eq 'SELECT ?s WHERE { ?s ?p ?o . VALUES (?o ?p) { ( UNDEF "2" ) ( "3" UNDEF ) } }'
      expect(subject.select.where.values(:s, RDF::URI('a'), RDF::URI('b')).to_s).to eq 'SELECT * WHERE { VALUES (?s) { ( <a> ) ( <b> ) } }'
    end

    it "supports GROUP BY" do
      expect(subject.select(:s).where([:s, :p, :o]).group_by(:s).to_s).to eq "SELECT ?s WHERE { ?s ?p ?o . } GROUP BY ?s"
      expect(subject.select(:s).where([:s, :p, :o]).group_by('?s').to_s).to eq "SELECT ?s WHERE { ?s ?p ?o . } GROUP BY ?s"
    end

    it "supports ORDER BY" do
      expect(subject.select.where([:s, :p, :o]).order_by(:o).to_s).to eq "SELECT * WHERE { ?s ?p ?o . } ORDER BY ?o"
      expect(subject.select.where([:s, :p, :o]).order_by(:o, :p).to_s).to eq "SELECT * WHERE { ?s ?p ?o . } ORDER BY ?o ?p"
      expect(subject.select.where([:s, :p, :o]).order_by('?o').to_s).to eq "SELECT * WHERE { ?s ?p ?o . } ORDER BY ?o"
      expect(subject.select.where([:s, :p, :o]).order_by('ASC(?o)').to_s).to eq "SELECT * WHERE { ?s ?p ?o . } ORDER BY ASC(?o)"
      expect(subject.select.where([:s, :p, :o]).order_by('DESC(?o)').to_s).to eq "SELECT * WHERE { ?s ?p ?o . } ORDER BY DESC(?o)"
      expect(subject.select.where([:s, :p, :o]).order_by(o: :asc).to_s).to eq "SELECT * WHERE { ?s ?p ?o . } ORDER BY ASC(?o)"
      expect(subject.select.where([:s, :p, :o]).order_by(o: :desc).to_s).to eq "SELECT * WHERE { ?s ?p ?o . } ORDER BY DESC(?o)"
      expect(subject.select.where([:s, :p, :o]).order_by(o: :asc, p: :desc).to_s).to eq "SELECT * WHERE { ?s ?p ?o . } ORDER BY ASC(?o) DESC(?p)"
      expect(subject.select.where([:s, :p, :o]).order_by([:o, :asc]).to_s).to eq "SELECT * WHERE { ?s ?p ?o . } ORDER BY ASC(?o)"
      expect(subject.select.where([:s, :p, :o]).order_by([:o, :desc]).to_s).to eq "SELECT * WHERE { ?s ?p ?o . } ORDER BY DESC(?o)"
      expect(subject.select.where([:s, :p, :o]).order_by([:o, :asc], [:p, :desc]).to_s).to eq "SELECT * WHERE { ?s ?p ?o . } ORDER BY ASC(?o) DESC(?p)"
      expect { subject.select.where([:s, :p, :o]).order_by(42).to_s }.to raise_error(ArgumentError)
      expect { subject.select.where([:s, :p, :o]).order_by(:o, 42).to_s }.to raise_error(ArgumentError)
      expect { subject.select.where([:s, :p, :o]).order_by([:o]).to_s }.to raise_error(ArgumentError)
      expect { subject.select.where([:s, :p, :o]).order_by([:o, :csa]).to_s }.to raise_error(ArgumentError)
      expect { subject.select.where([:s, :p, :o]).order_by([:o, :asc, 42]).to_s }.to raise_error(ArgumentError)
      expect { subject.select.where([:s, :p, :o]).order_by(o: 42).to_s }.to raise_error(ArgumentError)
      expect { subject.select.where([:s, :p, :o]).order_by(42 => :asc).to_s }.to raise_error(ArgumentError)
    end

    it "supports ORDER BY ASC" do
      expect(subject.select.where([:s, :p, :o]).order.asc(:o).to_s).to eq "SELECT * WHERE { ?s ?p ?o . } ORDER BY ASC(?o)"
      expect(subject.select.where([:s, :p, :o]).asc(:o).to_s).to eq "SELECT * WHERE { ?s ?p ?o . } ORDER BY ASC(?o)"
      expect { subject.select.where([:s, :p, :o]).order.asc(:o, :p).to_s }.to raise_error(ArgumentError)
    end

    it "supports ORDER BY DESC" do
      expect(subject.select.where([:s, :p, :o]).order.desc(:o).to_s).to eq "SELECT * WHERE { ?s ?p ?o . } ORDER BY DESC(?o)"
      expect(subject.select.where([:s, :p, :o]).desc(:o).to_s).to eq "SELECT * WHERE { ?s ?p ?o . } ORDER BY DESC(?o)"
      expect { subject.select.where([:s, :p, :o]).order.desc(:o, :p).to_s }.to raise_error(ArgumentError)
    end

    it "supports OFFSET" do
      expect(subject.select.where([:s, :p, :o]).offset(100).to_s).to eq "SELECT * WHERE { ?s ?p ?o . } OFFSET 100"
    end

    it "supports LIMIT" do
      expect(subject.select.where([:s, :p, :o]).limit(10).to_s).to eq "SELECT * WHERE { ?s ?p ?o . } LIMIT 10"
    end

    it "supports OFFSET with LIMIT" do
      expect(subject.select.where([:s, :p, :o]).offset(100).limit(10).to_s).to eq "SELECT * WHERE { ?s ?p ?o . } OFFSET 100 LIMIT 10"
      expect(subject.select.where([:s, :p, :o]).slice(100, 10).to_s).to eq "SELECT * WHERE { ?s ?p ?o . } OFFSET 100 LIMIT 10"
    end

    it "supports string PREFIX" do
      prefixes = ["dc: <http://purl.org/dc/elements/1.1/>", "foaf: <http://xmlns.com/foaf/0.1/>"]
      expect(subject.select.prefix(prefixes[0]).prefix(prefixes[1]).where([:s, :p, :o]).to_s).to eq "PREFIX dc: <http://purl.org/dc/elements/1.1/> PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT * WHERE { ?s ?p ?o . }"
    end

    it "supports hash PREFIX" do
      prefixes = [{dc: RDF::URI("http://purl.org/dc/elements/1.1/")}, {foaf: RDF::URI("http://xmlns.com/foaf/0.1/")}]
      expect(subject.select.prefix(prefixes[0]).prefix(prefixes[1]).where([:s, :p, :o]).to_s).to eq "PREFIX dc: <http://purl.org/dc/elements/1.1/> PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT * WHERE { ?s ?p ?o . }"
    end

    it "supports multiple values in PREFIX hash" do
      expect(subject.select.prefix(dc: RDF::URI("http://purl.org/dc/elements/1.1/"), foaf: RDF::URI("http://xmlns.com/foaf/0.1/")).where([:s, :p, :o]).to_s).to eq "PREFIX dc: <http://purl.org/dc/elements/1.1/> PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT * WHERE { ?s ?p ?o . }"
    end

    it "raises an ArgumentError for invalid PREFIX type" do
      inavlid_prefix_types = [RDF::URI('missing prefix hash'), 0, []]
      inavlid_prefix_types.each do |invalid_arg|
        expect { subject.select.prefix(invalid_arg) }.to raise_error ArgumentError, "prefix must be a kind of String or a Hash"
      end
    end

    it "supports OPTIONAL" do
      expect(subject.select.where([:s, :p, :o]).optional([:s, RDF.type, :o], [:s, RDF::URI("http://purl.org/dc/terms/abstract"), :o]).to_s).to eq "SELECT * WHERE { ?s ?p ?o . OPTIONAL { ?s a ?o . ?s <http://purl.org/dc/terms/abstract> ?o . } }"
    end

    it "supports OPTIONAL with filter in block" do
      expect(subject.select.where([:s, :p, :o]).optional([:s, RDF.value, :o]) {filter("langmatches(lang(?o), 'en')")}.to_s).to eq "SELECT * WHERE { ?s ?p ?o . OPTIONAL { ?s <http://www.w3.org/1999/02/22-rdf-syntax-ns#value> ?o . FILTER(langmatches(lang(?o), 'en')) . } }"
    end

    it "supports multiple OPTIONALs" do
      expect(subject.select.where([:s, :p, :o]).optional([:s, RDF.type, :o]).optional([:s, RDF::URI("http://purl.org/dc/terms/abstract"), :o]).to_s).to eq "SELECT * WHERE { ?s ?p ?o . OPTIONAL { ?s a ?o . } OPTIONAL { ?s <http://purl.org/dc/terms/abstract> ?o . } }"
    end

    it "supports subqueries" do
      subquery = subject.select.where([:s, :p, :o])
      expect(subject.select.where(subquery).where([:s, :p, :o]).to_s).to eq "SELECT * WHERE { { SELECT * WHERE { ?s ?p ?o . } } . ?s ?p ?o . }"
    end

    it "supports subqueries using block" do
      expect(subject.select.where([:s, :p, :o]) {select.where([:s, :p, :o])}.to_s).to eq "SELECT * WHERE { { SELECT * WHERE { ?s ?p ?o . } } . ?s ?p ?o . }"
    end

    it "expects results not statements" do
      expect(subject.select.where([:s, :p, :o])).not_to be_expects_statements
    end

    context "with property paths" do
      it "supports the InversePath expression" do
        expect(subject.select.where([:s, ["^",RDF::RDFS.subClassOf], :o]).to_s).to eq "SELECT * WHERE { ?s ^<#{RDF::RDFS.subClassOf}> ?o . }"
      end
      it "supports the SequencePath expression" do
        expect(subject.select.where([:s, [RDF.type,"/",RDF::RDFS.subClassOf], :o]).to_s).to eq "SELECT * WHERE { ?s a/<#{RDF::RDFS.subClassOf}> ?o . }"
      end
      it "supports the AlternativePath expression" do
        expect(subject.select.where([:s, [RDF.type,"|",RDF::RDFS.subClassOf], :o]).to_s).to eq "SELECT * WHERE { ?s a|<#{RDF::RDFS.subClassOf}> ?o . }"
      end
      it "supports the ZeroOrMore expression" do
        expect(subject.select.where([:s, [RDF::RDFS.subClassOf,"*"], :o]).to_s).to eq "SELECT * WHERE { ?s <#{RDF::RDFS.subClassOf}>* ?o . }"
      end
      it "supports the OneOrMore expression" do
        expect(subject.select.where([:s, [RDF::RDFS.subClassOf,"+"], :o]).to_s).to eq "SELECT * WHERE { ?s <#{RDF::RDFS.subClassOf}>+ ?o . }"
      end
      it "supports the ZeroOrOne expression" do
        expect(subject.select.where([:s, [RDF::RDFS.subClassOf,"?"], :o]).to_s).to eq "SELECT * WHERE { ?s <#{RDF::RDFS.subClassOf}>? ?o . }"
      end
      it "supports the NegatedPropertySet expression" do
        expect(subject.select.where([:s, ["!",[RDF::RDFS.subClassOf,"|",RDF.type]], :o]).to_s).to eq "SELECT * WHERE { ?s !(<#{RDF::RDFS.subClassOf}>|a) ?o . }"
      end
    end

    context "with unions" do
      it "supports pattern arguments" do
        expect(subject.select.where([:s, :p, :o]).union([:s, :p, :o]).to_s).to eq "SELECT * WHERE { ?s ?p ?o . } UNION { ?s ?p ?o . }"
      end

      it "supports query arguments" do
        subquery = subject.select.where([:s, :p, :o])
        expect(subject.select.where([:s, :p, :o]).union(subquery).to_s).to eq "SELECT * WHERE { ?s ?p ?o . } UNION { ?s ?p ?o . }"
      end

      it "supports block" do
        expect(subject.select.where([:s, :p, :o]).union {|q| q.where([:s, :p, :o])}.to_s).to eq "SELECT * WHERE { ?s ?p ?o . } UNION { ?s ?p ?o . }"
      end

      it "rejects mixed arguments" do
        subquery = subject.select.where([:s, :p, :o])
        expect {subject.select.where([:s, :p, :o]).union([:s, :p, :o], subquery)}.to raise_error(ArgumentError)
      end

      it "rejects arguments and block" do
        expect {subject.select.where([:s, :p, :o]).union([:s, :p, :o]) {|q| q.where([:s, :p, :o])}}.to raise_error(ArgumentError)
      end
    end

    context "with minus" do
      it "supports pattern arguments" do
        expect(subject.select.where([:s, :p, :o]).minus([:s, :p, :o]).to_s).to eq "SELECT * WHERE { ?s ?p ?o . MINUS { ?s ?p ?o . } }"
      end

      it "supports query arguments" do
        subquery = subject.select.where([:s, :p, :o])
        expect(subject.select.where([:s, :p, :o]).minus(subquery).to_s).to eq "SELECT * WHERE { ?s ?p ?o . MINUS { ?s ?p ?o . } }"
      end

      it "supports block" do
        expect(subject.select.where([:s, :p, :o]).minus {|q| q.where([:s, :p, :o])}.to_s).to eq "SELECT * WHERE { ?s ?p ?o . MINUS { ?s ?p ?o . } }"
      end

      it "rejects mixed arguments" do
        subquery = subject.select.where([:s, :p, :o])
        expect {subject.select.where([:s, :p, :o]).minus([:s, :p, :o], subquery)}.to raise_error(ArgumentError)
      end

      it "rejects arguments and block" do
        expect {subject.select.where([:s, :p, :o]).minus([:s, :p, :o]) {|q| q.where([:s, :p, :o])}}.to raise_error(ArgumentError)
      end
    end

    context "with SERVICE" do
      it "supports pattern arguments" do
        expect(subject.select.where([:s, :p1, :o1]).service(:l, [:s, :p2, :o2]).to_s).to eq "SELECT * WHERE { ?s ?p1 ?o1 . SERVICE ?l { ?s ?p2 ?o2 . } }"
      end

      it "supports pattern arguments with URI endpoint" do
        expect(subject.select.where([:s, :p1, :o1]).service(RDF::URI("http://example.com/endpoint"), [:s, :p2, :o2]).to_s).to eq "SELECT * WHERE { ?s ?p1 ?o1 . SERVICE <http://example.com/endpoint> { ?s ?p2 ?o2 . } }"
      end

      it "supports SILENT option" do
        expect(subject.select.where([:s, :p1, :o1]).service(:l, [:s, :p2, :o2], silent: true).to_s).to eq "SELECT * WHERE { ?s ?p1 ?o1 . SERVICE SILENT ?l { ?s ?p2 ?o2 . } }"
      end

      it "supports query arguments" do
        subquery = subject.select.where([:s, :p, :o])
        expect(subject.select.where([:s, :p, :o]).service(:l, subquery).to_s).to eq "SELECT * WHERE { ?s ?p ?o . SERVICE ?l { ?s ?p ?o . } }"
      end

      it "supports block" do
        expect(subject.select.where([:s, :p, :o]).service(:l) {|q| q.where([:s, :p, :o])}.to_s).to eq "SELECT * WHERE { ?s ?p ?o . SERVICE ?l { ?s ?p ?o . } }"
      end

      it "errors with no subqueries" do
        expect {subject.select.where([:s, :p, :o]).service(:l)}.to raise_error(ArgumentError)
      end

      it "rejects mixed arguments" do
        subquery = subject.select.where([:s, :p, :o])
        expect {subject.select.where([:s, :p, :o]).service(?l, [:s, :p, :o], subquery)}.to raise_error(ArgumentError)
      end

      it "rejects arguments and block" do
        expect {subject.select.where([:s, :p, :o]).service(?l[:s, :p, :o]) {|q| q.where([:s, :p, :o])}}.to raise_error(ArgumentError)
      end
    end
  end

  context "when building DESCRIBE queries" do
    it "supports basic graph patterns" do
      expect(subject.describe.where([:s, :p, :o]).to_s).to eq "DESCRIBE * WHERE { ?s ?p ?o . }"
    end

    it "supports projection" do
      expect(subject.describe(:s).where([:s, :p, :o]).to_s).to eq "DESCRIBE ?s WHERE { ?s ?p ?o . }"
      expect(subject.describe(:s, :p).where([:s, :p, :o]).to_s).to eq "DESCRIBE ?s ?p WHERE { ?s ?p ?o . }"
      expect(subject.describe(:s, :p, :o).where([:s, :p, :o]).to_s).to eq "DESCRIBE ?s ?p ?o WHERE { ?s ?p ?o . }"
    end

    it "supports RDF::URI arguments" do
      uris = ['http://www.bbc.co.uk/programmes/b007stmh#programme', 'http://www.bbc.co.uk/programmes/b00lg2xb#programme']
      expect(subject.describe(RDF::URI.new(uris[0]),RDF::URI.new(uris[1])).to_s).to eq "DESCRIBE <#{uris[0]}> <#{uris[1]}>"
    end

    it "expects statements not results" do
      expect(subject.describe(:s).where([:s, :p, :o])).to be_expects_statements
    end
  end

  context "when building CONSTRUCT queries" do
    it "supports basic graph patterns" do
      expect(subject.construct([:s, :p, :o]).where([:s, :p, :o]).to_s).to eq "CONSTRUCT { ?s ?p ?o . } WHERE { ?s ?p ?o . }"
    end

    it "expects statements not results" do
      expect(subject.construct([:s, :p, :o]).where([:s, :p, :o])).to be_expects_statements
    end
  end

  context "issues" do
    it "issue #96" do
      expect {
        require 'sparql/client'
        SPARQL::Client::Query
          .select
          .where(%i[s p o])
          .values(:s, RDF::URI('http://example.com/1'), RDF::URI('http://example.com/2'))
      }.not_to raise_error
    end
  end
end


text:
require "bundler/setup"
require 'rspec/its'
require 'rdf/spec'

begin
  require 'simplecov'
  require 'simplecov-lcov'

  SimpleCov::Formatter::LcovFormatter.config do |config|
    #Coveralls is coverage by default/lcov. Send info results
    config.report_with_single_file = true
    config.single_report_path = 'coverage/lcov.info'
  end

  SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
    SimpleCov::Formatter::HTMLFormatter,
    SimpleCov::Formatter::LcovFormatter
  ])
  SimpleCov.start do
    add_filter "/spec/"
  end
rescue LoadError => e
  STDERR.puts "Coverage Skipped: #{e.message}"
end
require 'sparql/client'

RSpec.configure do |config|
  config.include(RDF::Spec::Matchers)
  config.filter_run focus: true
  config.run_all_when_everything_filtered = true
end


text:
PREFIX dc: <http://purl.org/dc/terms/>
PREFIX doap: <http://usefulinc.com/ns/doap#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

CLEAR ALL;
INSERT DATA {
  <https://rubygems.org/gems/rdf> a doap:Project;
    doap:name "RDF.rb";
    doap:homepage <https://rubygems.org/gems/rdf>;
    doap:license <https://unlicense.org/1.0/>;
    doap:shortdesc "A Ruby library for working with Resource Description Framework (RDF) data."@en;
    doap:description "RDF.rb is a pure-Ruby library for working with Resource Description Framework (RDF) data."@en;
    doap:created "2007-10-23";
    doap:platform "Ruby";
    doap:category <http://dbpedia.org/resource/Resource_Description_Framework>,
                  <http://dbpedia.org/resource/Ruby_(programming_language)>;
    doap:implements <http://www.w3.org/TR/rdf-concepts/>,
                    <http://sw.deri.org/2008/07/n-quads/>,
                    <http://www.w3.org/2001/sw/RDFCore/ntriples/>;
    doap:download-page <httpss://rubygems.org/gems/rdf/>;
    doap:bug-database <https://gighub.com/ruby-rdf/rdf/issues>;
    doap:blog <https://ar.to/>;
    foaf:maker <https://ar.to/#self>;
    dc:creator <https://ar.to/#self>;
    doap:developer <https://ar.to/#self>,
                   <https://bhuga.net/#ben>,
                    <https://greggkellogg.net/foaf#me>;
    doap:maintainer <https://ar.to/#self>,
                    <https://bhuga.net/#ben>,
                    <https://greggkellogg.net/foaf#me>;
    doap:documenter <https://ar.to/#self>,
                    <https://bhuga.net/#ben>,
                    <https://greggkellogg.net/foaf#me>;
    doap:helper [
      a foaf:Person; foaf:name "Călin Ardelean"; foaf:mbox_sha1sum "274bd18402fc773ffc0606996aa1fb90b603aa29"
    ], [
      a foaf:Person; foaf:name "Danny Gagne"; foaf:mbox_sha1sum "6de43e9cf7de53427fea9765706703e4d957c17b"
    ], [
      a foaf:Person; foaf:name "Joey Geiger"; foaf:mbox_sha1sum "f412d743150d7b27b8468d56e69ca147917ea6fc"
    ], [
      a foaf:Person; foaf:name "Fumihiro Kato"; foaf:mbox_sha1sum "d31fdd6af7a279a89bf09fdc9f7c44d9d08bb930"
    ], [
      a foaf:Person; foaf:name "Naoki Kawamukai"; foaf:mbox_sha1sum "5bdcd8e2af4f5952aaeeffbdd371c41525ec761d"
    ], [
      a foaf:Person; foaf:name "Hellekin O. Wolf"; foaf:mbox_sha1sum "c69f3255ff0639543cc5edfd8116eac8df16fab8"
    ], [
      a foaf:Person; foaf:name "John Fieber"; foaf:mbox_sha1sum "f7653fc1ac0e82ebb32f092389bd5fc728eaae12"
    ], [
      a foaf:Person; foaf:name "Keita Urashima"; foaf:mbox_sha1sum "2b4247b6fd5bb4a1383378f325784318680d5ff9"
    ], [
      a foaf:Person; foaf:name "Pius Uzamere"; foaf:mbox_sha1sum "bedbbf2451e5beb38d59687c0460032aff92cd3c"
    ] .

  <https://ar.to/#self> a foaf:Person;
    foaf:name "Arto Bendiken";
    foaf:mbox <mailto:arto@bendiken.net>;
    foaf:mbox_sha1sum "a033f652c84a4d73b8c26d318c2395699dd2bdfb",
                      "d0737cceb55eb7d740578d2db1bc0727e3ed49ce";
    foaf:homepage <http://ar.to/>;
    foaf:made <https://rubygems.org/gems/rdf>;
    rdfs:isDefinedBy <https://ar.to/> .

  <https://bhuga.net/#ben> a foaf:Person;
    foaf:name "Ben Lavender";
    foaf:mbox <mailto:blavender@gmail.com>;
    foaf:mbox_sha1sum "dbf45f4ffbd27b67aa84f02a6a31c144727d10af";
    foaf:homepage <https://bhuga.net/>;
    rdfs:isDefinedBy <https://bhuga.net/> .

  <https://greggkellogg.net/foaf#me> a foaf:Person;
    foaf:name "Gregg Kellogg";
    foaf:mbox <mailto:gregg@greggkellogg.net>;
    foaf:mbox_sha1sum "35bc44e6d0070e5ad50ccbe0d24403c96af2b9bd";
    foaf:homepage <https://greggkellogg.net/>;
    rdfs:isDefinedBy <https://greggkellogg.net/foaf> .

  <http://example.org/xi1> <http://example.org/p> "1"^^<http://www.w3.org/2001/XMLSchema#integer> .
  <http://example.org/xi2> <http://example.org/p> "1"^^<http://www.w3.org/2001/XMLSchema#integer> .
  <http://example.org/xi3> <http://example.org/p> "01"^^<http://www.w3.org/2001/XMLSchema#integer> .
  <http://example.org/xd1> <http://example.org/p> "1.0e0"^^<http://www.w3.org/2001/XMLSchema#double> .
  <http://example.org/xd2> <http://example.org/p> "1.0"^^<http://www.w3.org/2001/XMLSchema#double> .
  <http://example.org/xd3> <http://example.org/p> "1"^^<http://www.w3.org/2001/XMLSchema#double> .
  <http://example.org/xt1> <http://example.org/p> "zzz"^^<http://example.org/myType> .
  <http://example.org/xp1> <http://example.org/p> "zzz" .
  <http://example.org/xp2> <http://example.org/p> "1" .
  <http://example.org/xu> <http://example.org/p> <http://example.org/z> .
}


text:
<?xml version="1.0"?>
<sparql xmlns="http://www.w3.org/2005/sparql-results#">
  <head></head>

  <boolean>false</boolean>
</sparql>


text:
<?xml version="1.0"?>
<sparql xmlns="http://www.w3.org/2005/sparql-results#">
  <head>
    <variable name="x"/>
    <variable name="hpage"/>
    <variable name="name"/>
    <variable name="age"/>
    <variable name="mbox"/>
    <variable name="triple"/>
  </head>
  <results>
    <result>
      <binding name="x">
        <bnode>r2</bnode>
      </binding>
      <binding name="hpage">
        <uri>http://work.example.org/bob/</uri>
      </binding>
      <binding name="name">
        <literal xml:lang="en">Bob</literal>
      </binding>
      <binding name="age">
        <literal datatype="http://www.w3.org/2001/XMLSchema#integer">30</literal>
      </binding>
      <binding name="mbox">
        <uri>mailto:bob@work.example.org</uri>
      </binding>
      <binding name="_empty"></binding>
      <binding name="triple">
        <triple>
          <subject><uri>http://work.example.org/s</uri></subject>
          <predicate><uri>http://work.example.org/p</uri></predicate>
          <object><uri>http://work.example.org/o</uri></object>
        </triple>
      </binding>
    </result>
  </results>
</sparql>


text:
<?xml version="1.0"?>
<sparql xmlns="http://www.w3.org/2005/sparql-results#">
  <head></head>

  <boolean>true</boolean>
</sparql>


text:
<?xml version="1.0"?>
<sparql
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:xs="http://www.w3.org/2001/XMLSchema#"
    xmlns="http://www.w3.org/2005/sparql-results#" >
  <head>
    <variable name="v"/>
    <variable name="w"/>
  </head>
  <results>
    <result>
      <binding name="v">
        <literal datatype="http://www.w3.org/2001/XMLSchema#integer">1</literal>
      </binding>
    </result>
  </results>
</sparql>


text:
@base         <https://rubygems.org/gems/sparql-client> .
@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix dc:   <http://purl.org/dc/terms/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix doap: <http://usefulinc.com/ns/doap#> .

<> a doap:Project ;
  doap:name          "SPARQL::Client" ;
  doap:homepage      <https://github.com/ruby-rdf/sparql-client> ;
  doap:license       <https://unlicense.org/1.0/> ;
  doap:shortdesc     "SPARQL client for RDF.rb."@en ;
  doap:description   """Executes SPARQL queries and updates against a remote SPARQL 1.0 or 1.1 endpoint,
                        or against a local repository. Generates SPARQL queries using a simple DSL."""@en ;
  doap:created       "2007-11-03" ;
  doap:programming-language "Ruby" ;
  doap:category      <https://dbpedia.org/resource/Resource_Description_Framework>,
                     <https://dbpedia.org/resource/Ruby_(programming_language)> ;
  doap:implements    <https://www.w3.org/TR/sparql11-query/>,
                     <https://www.w3.org/TR/sparql11-update/>,
                     <https://www.w3.org/TR/sparql11-results-json/>,
                     <https://www.w3.org/TR/sparql11-results-csv-tsv/>,
                     <https://www.w3.org/TR/rdf-sparql-XMLres/> ;
  doap:download-page <https://github.com/ruby-rdf/sparql-client>;
  doap:bug-database  <https://github.com/ruby-rdf/sparql-client/sparql-client/issues> ;
  doap:blog          <https://ar.to/>, <https://greggkellogg.net/> ;
  doap:developer     <https://ar.to/#self>, <https://bhuga.net/#ben>, <https://greggkellogg.net/foaf#me> ;
  doap:maintainer    <https://greggkellogg.net/foaf#me> ;
  doap:documenter    <https://ar.to/#self>, <https://bhuga.net/#ben>, <https://greggkellogg.net/foaf#me> ;
  doap:helper        [a foaf:Person ;
                      foaf:name "Christoph Badura" ;
                      foaf:mbox_sha1sum "3a9c4bbe13feec63b1c8292ebf90e8da6caa0afd"] ;
  doap:helper        [a foaf:Person ;
                      foaf:name "Fumihiro Kato" ;
                      foaf:mbox_sha1sum "d31fdd6af7a279a89bf09fdc9f7c44d9d08bb930"] ;
  doap:helper        [a foaf:Person ;
                      foaf:name "James Hetherington" ;
                      foaf:mbox_sha1sum "22358c247c092e1452c0ef5ac2fba612958061c9"] ;
  doap:helper        [a foaf:Person ;
                      foaf:name "Gabriel Horner" ;
                      foaf:mbox_sha1sum "f8ea1d1bc7c36b7b18f38d71236cac75c42cefce"] ;
  doap:helper        [a foaf:Person ;
                      foaf:name "Nicholas Humfrey" ;
                      foaf:mbox_sha1sum "9da296bcd486cbbfe4317b3f0317331d6a9577cf"] ;
  doap:helper        [a foaf:Person ;
                      foaf:name "Fumihiro Kato" ;
                      foaf:mbox_sha1sum "678b4203e9310073c9f1c073b2732ce56bf0a67f"] ;
  doap:helper        [a foaf:Person ;
                      foaf:name "David Nielsen" ;
                      foaf:mbox_sha1sum "f41dbb8acd06d9387d939a360707c976def9ed30"] ;
  doap:helper        [a foaf:Person ;
                      foaf:name "Thamaraiselvan Poomalai" ;
                      foaf:mbox_sha1sum "7aac96712ece896b4af1405144ca89525b509bde"] ;
  doap:helper        [a foaf:Person ;
                      foaf:name "Michael Sokol" ;
                      foaf:mbox_sha1sum "bd526552bc528245d80d17f16a1e8067f1cc0453"] ;
  doap:helper        [a foaf:Person ;
                      foaf:name "Yves Raimond" ;
                      foaf:mbox_sha1sum "3ca077e61d39ef6b476035a4a9d4dee6a1890766"] ;
  doap:helper        [a foaf:Person ;
                      foaf:name "Thomas Feron" ;
                      foaf:mbox_sha1sum "8c6ba34fcf8705a63af3858140ba0107b9ee756a"] ;
  foaf:maker         <https://ar.to/#self> ;
  dc:creator         <https://ar.to/#self> .

<http:s//ar.to/#self> a foaf:Person ;
  foaf:name          "Arto Bendiken" ;
  foaf:mbox          <mailto:arto@bendiken.net> ;
  foaf:mbox_sha1sum  "a033f652c84a4d73b8c26d318c2395699dd2bdfb",
                     "d0737cceb55eb7d740578d2db1bc0727e3ed49ce" ;
  foaf:homepage      <https://ar.to/> ;
  foaf:made          <>  .

<https://bhuga.net/#ben> a foaf:Person ;
  foaf:name          "Ben Lavender" ;
  foaf:mbox          <mailto:blavender@gmail.com> ;
  foaf:mbox_sha1sum  "dbf45f4ffbd27b67aa84f02a6a31c144727d10af" ;
  foaf:homepage      <https://bhuga.net/> .

<https://greggkellogg.net/foaf#me> a foaf:Person ;
  foaf:name          "Gregg Kellogg" ;
  foaf:mbox          <mailto:gregg@greggkellogg.net> ;
  foaf:mbox_sha1sum  "35bc44e6d0070e5ad50ccbe0d24403c96af2b9bd" ;
  foaf:homepage      <https://greggkellogg.net/>;
  rdfs:isDefinedBy   <https://greggkellogg.net/foaf> .


text:
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment
include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
  address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting richard@burntfen.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]

[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

repo_name: mntnr/awesome-contributing


text:
# Contribution Guidelines

First, thanks. Secondly, and ironically, there is not much here yet. If you have any suggestions for how to improve this repository, please open an issue or a pull request.

If you have examples of great contributing docs, open a new PR with them. Please use this format:

  ` - [Name](link) _Comment on why it is awesome._ - [@YourName](https://github.com/YourName)`.

Also:

- Check your spelling and grammar.
- Please add the entry in the correct section, in alphabetical order.
- Search previous suggestions before making a new one, as yours may be a duplicate.
- Make an individual pull request for each suggestion.
- The pull request and commit should have a useful title.
- Pull Requests without a personal comment will not be accepted until one is added.

Thank you!


text:
# Awesome-Contributing [![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/sindresorhus/awesome)

> Awesome contributing guides for open source development.

## Examples

- [atom](https://github.com/atom/atom/blob/master/CONTRIBUTING.md) _An extensive Contributing guide that is particularly good at answering questions by new users before they know enough to ask them._ - [@RichardLitt](https://github.com/RichardLitt)
- [Docker](https://github.com/docker/docker/blob/master/CONTRIBUTING.md) _Docker got everything right. Grats even from a non-addict, this is a very good contrib guide._ - [@FlorianHeigl](https://github.com/FlorianHeigl)
- [Pacote](https://github.com/zkat/pacote/blob/latest/CONTRIBUTING.md) _This is a pretty awesome example of a contributing file._ - [@dignifiedquire](https://github.com/dignifiedquire)
- [Puppet](https://github.com/puppetlabs/puppet/blob/master/CONTRIBUTING.md) _A very accessible guide. The additional resources list is especially helpful_. - [@RichardLitt](https://github.com/RichardLitt)
- [Rust Programming Language](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md) _A very complete contributing guide._ - [@sirodoht](https://github.com/sirodoht)
- [donet/corefix](https://github.com/dotnet/corefx/blob/master/Documentation/project-docs/contributing.md) _A short and concise contributing file._ - [@jzeferino](https://github.com/jzeferino)

## Templates

The [@Contribute-md Template](https://github.com/contribute-md/contribute-md-template) is detailed and cohesive, and should work for most projects.

[We All Contribute](https://github.com/WeAllJS/weallcontribute) is a JavaScript CLI tool that can help you create Contribute files according to their guidelines.

## Guides to writing a Contribute.md document

[GitHub guide here](https://help.github.com/articles/setting-guidelines-for-repository-contributors/) and [here](https://github.com/blog/1184-contributing-guidelines) are useful. GitHub [automatically opens](https://github.com/blog/1184-contributing-guidelines) up a banner pointing to a `Contribute.md` file. This means that anyone who opens an issue or a pull request will know to check your Contributing guidelines. Newcomers will be the main target - experienced users will have memorized anything in your Contribute, and won't need it to guide them. Because of this, you want to make sure it is as accessible as possible.

[MozillaScience's guide](https://mozillascience.github.io/working-open-workshop/contributing/) goes into depth about what to put into this guide, and is the best guide we've seen for how to write contributing docs in general.

## Contribute

We encourage all contributions to this repository! [Open an issue!](https://github.com/RichardLitt/awesome-contribute) Or open a Pull Request!

Note: All interaction here should conform to the [Code of Conduct](CODE_OF_CONDUCT.md).

## License

[![CC0](http://mirrors.creativecommons.org/presskit/buttons/88x31/svg/cc-zero.svg)](https://creativecommons.org/publicdomain/zero/1.0/)

To the extent possible under law, [Richard Littauer](https://burntfen.com) has waived all copyright and related or neighboring rights to this work.


text:
import gzip

in_file = "freebase-rdf-latest.gz"
out_file = "freebase-rdf-latest-literal_fixed.gz"

# datatype strings
datatype_string = {}
datatype_string["type.int"] = "<http://www.w3.org/2001/XMLSchema#integer>"
datatype_string["type.float"] = "<http://www.w3.org/2001/XMLSchema#float>"
datatype_string["type.boolean"] = "<http://www.w3.org/2001/XMLSchema#boolean>"

# get the properties with literal object value
type_map = {}
with open("numeric_properties.txt", "r") as f_in:
    for line in f_in:
        line = line.strip()
        pred, type = line.split("\t")
        type_map[pred] = datatype_string[type]

# update literal type line by line
f_in = gzip.open(in_file, "r")
f_out = gzip.open(out_file, "w")
line_num = 0
for line in f_in:
    line_num += 1
    if not line:
        continue
    subj, pred, obj, rest = line.split("\t")
    pred_t = pred[pred.rfind("/")+1:len(pred)-1]
    try:
        datatype_string = type_map[pred_t]
        if "^^" in obj:
          pass
        else:
            if "\"" in obj:
                obj = obj + "^^" + datatype_string
            else:
                obj = "\"" + obj + "\"^^" + datatype_string
            line = "\t".join([subj, pred, obj, rest])
    except:
        pass
    f_out.write(line)
    if line_num % 1000000 == 0:
        print(line_num)

f_in.close()
f_out.close()

repo_name: dki-lab/Freebase-Setup

repo_language: Python